From 92426f5ab3ec211c108d40345fdf67cff04aa527 Mon Sep 17 00:00:00 2001 From: Axel D <SetTrend@users.noreply.github.com> Date: Fri, 14 Dec 2018 16:52:20 +0100 Subject: [PATCH 01/13] CSS rules added for printing, script added to create chapter-wide documentation files from single files. --- concatenate-docs.js | 78 + package.json | 7 +- src/components/Footer/Footer.scss | 4 + src/components/Page/Page.jsx | 2 +- src/components/Page/Page.scss | 7 + src/components/PageLinks/PageLinks.scss | 4 + src/content/_all.md | 262 + src/content/api/_api_all.md | 3189 ++++++++++ src/content/concepts/_concepts_all.md | 1086 ++++ .../configuration/_configuration_all.md | 5315 +++++++++++++++++ src/content/contribute/_contribute_all.md | 979 +++ src/content/guides/_guides_all.md | 4880 +++++++++++++++ src/content/loaders/_loaders_all.md | 75 + src/content/migrate/_migrate_all.md | 786 +++ src/content/plugins/_plugins_all.md | 11 + 15 files changed, 16681 insertions(+), 4 deletions(-) create mode 100644 concatenate-docs.js create mode 100644 src/content/_all.md create mode 100644 src/content/api/_api_all.md create mode 100644 src/content/concepts/_concepts_all.md create mode 100644 src/content/configuration/_configuration_all.md create mode 100644 src/content/contribute/_contribute_all.md create mode 100644 src/content/guides/_guides_all.md create mode 100644 src/content/loaders/_loaders_all.md create mode 100644 src/content/migrate/_migrate_all.md create mode 100644 src/content/plugins/_plugins_all.md diff --git a/concatenate-docs.js b/concatenate-docs.js new file mode 100644 index 000000000000..5d2a7c48ec0f --- /dev/null +++ b/concatenate-docs.js @@ -0,0 +1,78 @@ +// start message +console.info("\x1b[0m\x1b[36mConcatenating help files of each directory to create chapter-wide help files to be used for printing help ...\x1b[0m"); + +// ------ various includes ------ +const fs = require("fs"); +const path = require("path"); +const os = require("os"); +const front = require("front-matter"); + +// root path +const rootPath = path.join("src", "content"); + +/* getDirectoryRecursive() recursively walks through + all sub directories of the provided root path, + concatenates the MarkDown files' content in + each directory, sorted by their FrontMatter sort + attribute, and creates a compound MarkDown file + named by using the directory name, prefixed by an + underscore and suffixed by "_all.md" from the + concatenated content in the corresponding directory. +*/ +(function getDirectoryRecursive(basePath) +{ + // log current working directory + console.log("\x1b[0m\x1b[32m " + basePath + "\x1b[0m"); + + // create destination file name of compound file + const targetFilePath = path.join(basePath, `${basePath.substr(rootPath.length).replace(/[/\\]/, "_")}_all.md`); + + if (fs.existsSync(targetFilePath)) fs.unlinkSync(targetFilePath); // delete target file if it already exists + + fs.readdir(basePath, function (err, fileNames) // list current working directory + { + if (err) throw err; + + let fileContents = []; + + for (let file of fileNames) // for each directory entry ... + { + const fullPath = path.join(basePath, file); + + if (fs.statSync(fullPath).isDirectory()) getDirectoryRecursive(fullPath); // if the directory entry is a directory, recurse into that directory + else if (fullPath.endsWith(".md")) // if the directory entry is a MarkDown file, add it to the list of files to be processed + { + let fc = fileContents[fileContents.length] = front(fs.readFileSync(fullPath).toString()); + + if (!fc.attributes.sort) --fileContents.length; // only include files providing a FrontMatter "sort" attribute + } + } + + // sort MarkDown files by FrontMatter "sort" attribute (QuickSort) + for (let i = 0;i < fileContents.length - 1;++i) + for (let j = i + 1;j < fileContents.length;++j) + { + const left = fileContents[i].attributes, right = fileContents[j].attributes; + + if (left.sort > right.sort + || left.sort == right.sort && left.title > right.title) + [fileContents[i], fileContents[j]] = [fileContents[j], fileContents[i]]; + } + + // write compound target file + const targetFile = fs.createWriteStream(targetFilePath); + + targetFile.on("error", (error) => { throw error; }); + + for (let file of fileContents) + { + targetFile.write(os.EOL + os.EOL + "# " + file.attributes.title + os.EOL); // use FrontMatter "title" attribute as main heading of target file + targetFile.write(file.body); + } + + targetFile.end(); + }); +})(rootPath); + +// end message +process.on("exit", () => { console.info("\x1b[0m\x1b[36mSuccessfully created \"_all.md\" help files in each directory within \"" + rootPath + "\".\x1b[0m"); }); \ No newline at end of file diff --git a/package.json b/package.json index 96f6834bb6f5..931acebc9f52 100644 --- a/package.json +++ b/package.json @@ -26,18 +26,19 @@ "scripts": { "start": "run-s -n init:generated fetch start-only", "start-only": "node ./antwar.bootstrap.js develop", - "build": "npm run init:generated && npm run fetch && rm -rf build/ && node ./antwar.bootstrap.js build && npm run sitemap && echo webpack.js.org > build/CNAME", + "build": "npm run init:generated && npm run fetch && rm -rf build/ && node ./antwar.bootstrap.js build && npm run sitemap && npm run chapterize && echo webpack.js.org > build/CNAME", "build-test": "npm run build && http-server build/", "deploy": "gh-pages -d build", "fetch": "sh src/scripts/fetch.sh", "init:generated": "mkdirp ./generated/loaders && mkdirp ./generated/plugins ", "lint": "run-s lint:*", "lint:js": "eslint . --ext .js,.jsx,.md", - "lint:markdown": "markdownlint --rules markdownlint-rule-emphasis-style --config ./.markdownlint.json *.md ./src/content/*.md ./src/content/**/*.md", + "lint:markdown": "markdownlint --rules markdownlint-rule-emphasis-style --config ./.markdownlint.json --ignore ./src/content/**/*_all.md *.md ./src/content/**/*.md", "lint:social": "alex . -q", "lint:prose": "cp .proselintrc ~/ && proselint src/content", "test": "npm run lint", - "sitemap": "cd build && sitemap-static --prefix=https://webpack.js.org/ > sitemap.xml" + "sitemap": "cd build && sitemap-static --prefix=https://webpack.js.org/ > sitemap.xml", + "chapterize": "node ./concatenate-docs.js" }, "husky": { "hooks": { diff --git a/src/components/Footer/Footer.scss b/src/components/Footer/Footer.scss index 106d52ec0de3..4388e8be401c 100644 --- a/src/components/Footer/Footer.scss +++ b/src/components/Footer/Footer.scss @@ -4,6 +4,10 @@ .footer { width: 100%; flex: 0 0 auto; + + @media print { + display: none !important; + } } .footer__inner { diff --git a/src/components/Page/Page.jsx b/src/components/Page/Page.jsx index a21ce4d20156..e2b93794f766 100644 --- a/src/components/Page/Page.jsx +++ b/src/components/Page/Page.jsx @@ -81,7 +81,7 @@ const Page = ({ page, section }) => { )} { contributors.length > 0 && ( - <div> + <div className="contributors__section"> <hr /> <h3>Contributors</h3> <Contributors contributors={ contributors } /> diff --git a/src/components/Page/Page.scss b/src/components/Page/Page.scss index 85c664e2fdfe..91b1b94bcafe 100644 --- a/src/components/Page/Page.scss +++ b/src/components/Page/Page.scss @@ -29,3 +29,10 @@ padding: 1.5em; } } + +.contributors__section, .interactive +{ + @media print { + display: none !important; + } +} \ No newline at end of file diff --git a/src/components/PageLinks/PageLinks.scss b/src/components/PageLinks/PageLinks.scss index 7f45b7ff1526..60624bdd51fc 100644 --- a/src/components/PageLinks/PageLinks.scss +++ b/src/components/PageLinks/PageLinks.scss @@ -2,6 +2,10 @@ @import 'functions'; .page-links { + @media print { + display: none !important; + } + position: absolute; display: none; top: 1.5em; diff --git a/src/content/_all.md b/src/content/_all.md new file mode 100644 index 000000000000..fb91d2979380 --- /dev/null +++ b/src/content/_all.md @@ -0,0 +1,262 @@ + + +# Comparison + +webpack is not the only module bundler out there. If you are choosing between using webpack or any of the bundlers below, here is a feature-by-feature comparison on how webpack fares against the current competition. + +| Feature | webpack/webpack | jrburke/requirejs | substack/node-browserify | jspm/jspm-cli | rollup/rollup | brunch/brunch | +|---------|-----------------|-------------------|--------------------------|---------------|---------------|---------------| +| Additional chunks are loaded on demand | __yes__ | __yes__ | no | [System.import](https://github.com/systemjs/systemjs/blob/master/docs/system-api.md#systemimportmodulename--normalizedparentname---promisemodule) | no | no | +| AMD `define` | __yes__ | __yes__ | [deamdify](https://github.com/jaredhanson/deamdify) | yes | [rollup-plugin-amd](https://github.com/piuccio/rollup-plugin-amd) | yes | +| AMD `require` | __yes__ | __yes__ | no | yes | no | yes | +| AMD `require` loads on demand | __yes__ | with manual configuration | no | yes | no | no | +| CommonJS `exports` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | +| CommonJS `require` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | +| CommonJS `require.resolve` | __yes__ | no | no | no | no | | +| Concat in require `require("./fi" + "le")` | __yes__ | no♦ | no | no | no | | +| Debugging support | __SourceUrl, SourceMaps__ | not required | SourceMaps | __SourceUrl, SourceMaps__ | __SourceUrl, SourceMaps__ | SourceMaps | +| Dependencies | 19MB / 127 packages | 11MB / 118 packages | __1.2MB / 1 package__ | 26MB / 131 packages | ?MB / 3 packages | | +| ES2015 `import`/`export` | __yes__ (webpack 2) | no | no | __yes__ | __yes__ | yes, via [es6 module transpiler](https://github.com/gcollazo/es6-module-transpiler-brunch) +| Expressions in require (guided) `require("./templates/" + template)` | __yes (all files matching included)__ | no♦ | no | no | no | no | +| Expressions in require (free) `require(moduleName)` | with manual configuration | no♦ | no | no | no | | +| Generate a single bundle | __yes__ | yes♦ | yes | yes | yes | yes | +| Indirect require `var r = require; r("./file")` | __yes__ | no♦ | no | no | no | | +| Load each file separate | no | yes | no | yes | no | no | +| Mangle path names | __yes__ | no | partial | yes | not required (path names are not included in the bundle) | no | +| Minimizing | terser | uglify, closure compiler | [uglifyify](https://github.com/hughsk/uglifyify) | yes | [uglify-plugin](https://github.com/TrySound/rollup-plugin-uglify) | [UglifyJS-brunch](https://github.com/brunch/uglify-js-brunch) +| Multi pages build with common bundle | with manual configuration | __yes__ | with manual configuration | with bundle arithmetic | no | no| +| Multiple bundles | __yes__ | with manual configuration | with manual configuration | yes | no | yes | +| Node.js built-in libs `require("path")` | __yes__ | no | __yes__ | __yes__ | [node-resolve-plugin](https://github.com/rollup/rollup-plugin-node-resolve) | | +| Other Node.js stuff | process, __dir/filename, global | - | process, __dir/filename, global | process, __dir/filename, global for cjs | global ([commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs)) | | +| Plugins | __yes__ | yes | __yes__ | yes | yes | yes | +| Preprocessing | __loaders, [transforms](https://github.com/webpack-contrib/transform-loader)__ | loaders | transforms | plugin translate | plugin transforms | compilers, optimizers | +| Replacement for browser | `web_modules`, `.web.js`, package.json field, alias config option | alias option | package.json field, alias option | package.json, alias option | no | | +| Requirable files | file system | __web__ | file system | through plugins | file system or through plugins | file system | +| Runtime overhead | __243B + 20B per module + 4B per dependency__ | 14.7kB + 0B per module + (3B + X) per dependency | 415B + 25B per module + (6B + 2X) per dependency | 5.5kB for self-executing bundles, 38kB for full loader and polyfill, 0 plain modules, 293B CJS, 139B ES2015 System.register before gzip | __none for ES2015 modules__ (other formats may have) | | +| Watch mode | yes | not required | [watchify](https://github.com/browserify/watchify) | not needed in dev | [rollup-watch](https://github.com/rollup/rollup-watch) | yes | + +♦ in production mode (opposite in development mode) + +X is the length of the path string + + +## Bundling vs. Loading + +It's important to note some key differences between _loading_ and _bundling_ modules. A tool like [SystemJS](https://github.com/systemjs/systemjs), which can be found under the hood of [JSPM](https://github.com/jspm/jspm-cli), is used to load and transpile modules at runtime in the browser. This differs significantly from webpack, where modules are transpiled (through "loaders") and bundled before hitting the browser. + +Each method has its advantages and disadvantages. Loading and transpiling modules at runtime can add a lot of overhead for larger sites and applications comprised of many modules. For this reason, SystemJS makes more sense for smaller projects where fewer modules are required. However, this may change a bit as [HTTP/2](https://http2.github.io/) will improve the speed at which files can be transferred from server to client. Note that HTTP/2 doesn't change anything about _transpiling_ modules, which will always take longer when done client-side. + + +# Branding Guidelines + +Here you can find __webpack__ project brand guidelines, assets, and license. See our official [media repository](https://github.com/webpack/media) for more information and to find the [license](https://github.com/webpack/media/blob/master/LICENSE) that governs this work. Click any of the images to download them. + + +## The Name + +webpack should __always__ be written in lower-case letters, even at the beginning of a sentence. + + +## Logo + +The webpack logo should be placed on a white background with enough space around it like this: + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-white-bg.png" alt="webpack logo default with proper spacing on light background" /> + +[svg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.jpg) + +Just double the size of the inner dark blue cube to get an idea how much space the logo should have. + +For dark backgrounds, you can use the negative version of the logo: + +<div style="display: block; background: #111;"> + <img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-dark-bg.png" alt="webpack logo default with proper spacing on light background" /> +</div> + +[svg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.jpg) + +T> Please use the __icon + text__ whenever possible. + + +## Icon only + +__The icon is designed to be used in layout-constrained areas. As previously stated, please prefer icon + text.__ + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon.png" width="250" alt="icon example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon.jpg) + +Square-sized icon for bigger areas (like avatars or profile pictures): + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-big.png" width="250" alt="icon square big example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon-square-big.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-big.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-big.jpg) + +Square-sized icon for smaller areas (like favicons): + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-small.png" width="50" alt="icon square small example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon-square-small.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-small.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-small.jpg) + +T> For those of you following our guidelines and have gotten this far, we've made a special smaller size image used especially for custom emoji (like in a slack or gitter channel ;)) + +<img src="/assets/icon-square-small-slack.png" width="50" alt="icon square small example"> + + +## Font + +We use the beautiful [Geomanist Medium](http://atipofoundry.com/fonts/geomanist) font from the extremely talented folks at the [Atipo Foundry](http://atipofoundry.com/) who provide the entire font family at a 'pay what you want' model. + + +## Color Palette + +The following colors are used throughout the site in various combinations and on our fancy clothing line launched with the help of [Open Collective](https://opencollective.com/) and [Threadless](https://medium.com/u/840563ee2a56) over at the [official webpack store](https://webpack.threadless.com/collections/the-final-release-collection/)! + +| Color Name | HEX Code | RGB Code | Sample +|---------------|---------------|-----------------------|------------------------------- +| Malibu: | HEX `#8dd6f9` | `rgb: 141, 214, 249` | <div style="background-color: #8dd6f9;"> </div> +| Denim: | HEX `#1d78c1` | `rgb: 29, 120, 193` | <div style="background-color: #1d78c1;"> </div> +| Fiord: | HEX `#465E69` | `rgb: 70, 94, 105` | <div style="background-color: #465E69;"> </div> +| Outer Space: | HEX `#2B3A42` | `rgb: 43, 58, 66` | <div style="background-color: #2B3A42;"> </div> +| White: | HEX `#ffffff` | `rgb: 255, 255, 255` | <div style="background-color: #ffffff;"> </div> +| Concrete: | HEX `#f2f2f2` | `rgb: 242, 242, 242` | <div style="background-color: #f2f2f2;"> </div> +| Alto: | HEX `#dedede` | `rgb: 222, 222, 222` | <div style="background-color: #dedede;"> </div> +| Dusty Gray: | HEX `#999999` | `rgb: 153, 153, 153` | <div style="background-color: #999999;"> </div> +| Dove Gray: | HEX `#666666` | `rgb: 102, 102, 102` | <div style="background-color: #666666;"> </div> +| Emperor: | HEX `#535353` | `rgb: 83, 83, 83` | <div style="background-color: #535353;"> </div> +| Mine Shaft: | HEX `#333333` | `rgb: 51, 51, 51` | <div style="background-color: #333333;"> </div> + +In addition, you can grab the following file types directly from these links: + +[psd](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.psd) | [png](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.png) + | [ai](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.ai) | [svg](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.svg) + + +## License + +The logo and the brand name are __not MIT licensed__. Please check [our LICENSE](https://github.com/webpack/media/blob/master/LICENSE) for usage guidelines. + + +# Glossary + +This index lists common terms used throughout the webpack ecosystem. + + +## A + +- [__Asset__](/guides/asset-management/): This a general term for the images, fonts, media, and any other kind of files that are typically used in websites and other applications. These typically end up as individual files within the [output](/glossary#o) but can also be inlined via things like the [style-loader](/loaders/style-loader) or [url-loader](/loaders/url-loader). + + +## B + +- [__Bundle__](/guides/getting-started/#creating-a-bundle): Produced from a number of distinct modules, bundles contain the final versions of source files that have already undergone the loading and compilation process. +- [__Bundle Splitting__](/guides/code-splitting): This process offers one way of optimizing a build, allowing webpack to generate multiple bundles for a single application. As a result, each bundle can be isolated from changes effecting others, reducing the amount of code that needs to be republished and therefore re-downloaded by the client and taking advantage of browser caching. + + +## C + +- __Chunk__: This webpack-specific term is used internally to manage the bundling process. Bundles are composed out of chunks, of which there are several types (e.g. entry and child). Typically, _chunks_ directly correspond with the output _bundles_ however, there are some configurations that don't yield a one-to-one relationship. +- [__Code Splitting__](/guides/code-splitting/): Refers to dividing your code into various bundles/chunks which you can then load on demand instead of loading a single bundle containing everything. +- [__Configuration__](/concepts/configuration/): webpack config file is a plain old JavaScript file that exports an object. This object is then processed by webpack based upon its defined properties. + + +## D + +- [__Dependency Graph__](/concepts/dependency-graph): Any time one file depends on another, webpack treats this as a _dependency_. Starting from an entry point(s), webpack recursively builds a dependency graph that includes every module/asset your application needs. + + +## E + +- [__Entry Point__](/concepts/entry-points): The entry point tells webpack where to start and follows the graph of dependencies to know what to bundle. You can think of your application's entry point(s) as the __contextual root(s)__ of what you want bundled. + + +## F + +## G + +## H + +- [__Hot Module Replacement (HMR)__](/concepts/hot-module-replacement): A process that exchanges, adds, or removes `modules` while an application is running without a full page reload. + + +## I + +## J + +## K + +## L + +- [__Loaders__](/concepts/loaders): Transformations that are applied on the source code of a module. They allow you to pre-process files as you `require()` or "load" them. Similar to a 'task-runner'. + + +## M + +- [__Module__](/concepts/modules): Discrete chunks of functionality that provide a smaller surface area than a full program. Well-written modules provide solid abstractions and encapsulation boundaries which make up a coherent design and clear purpose. +- [__Module Resolution__](/concepts/module-resolution/): A module can be required as a dependency from another module and a resolver is a library which helps in locating a module by its absolute path.. Modules are searched for inside all directories specified in `resolve.modules`. + + +## N + +## O + +- [__Output__](/concepts/output): Option(s) specifying where to output the compiled files to disk. + > _Note, that while there can be multiple entry points, only one output configuration is specified._ + + +## P + +- [__Plugin__](/concepts/plugins): A JavaScript object that has an `apply` property. This `apply` property is called by the webpack compiler, giving access to the entire compilation lifecycle. These packages will typically extend compilation functionality in one way or another. + + +## Q + +## R + +- [__Request__](/guides/dependency-management/): Refers to the expression in the require/import statement, e.g. _require("./template/" + name + ".ejs")_, the request is _"./template/" + name + ".ejs"_. + +## S + +## T + +- [__Target__](/configuration/target/): User configured deployment target(s) [listed here](/configuration/target/) to compile for a specific environment like the browser, NodeJS, or Electron. +- [__Tree Shaking__](/guides/tree-shaking/): Unused/Excess code elimination, or more precisely, live code importing. Compilers like webpack will accomplish this by analyzing the various kinds `import` statements and usage of the imported code to determine what parts of dependencies are actually being utilized, dropping parts of the "tree" that are not. + + +## U + +## V + +- [__Vendor Entry Point__](/concepts/entry-points/#separate-app-and-vendor-entries): Create dependency graphs starting at both `app.js` and `vendors.js`. These graphs are completely separate and independent of each other to allow leverage of `CommonsChunkPlugin` and extract any vendor references from your app bundle into your vendor bundle. Helps achieve a common pattern in webpack known as [long-term vendor-caching](/guides/caching/). + + +## W + +- [__webpack__](/): A highly configurable [module](/concepts/modules) bundler for modern JavaScript applications + + +## X + +## Y + +## Z + + +# License + +## webpack + +webpack is [MIT licensed](https://github.com/webpack/webpack/blob/master/LICENSE). + +## webpack logo and icon + +The webpack logo and icon are under a different license which can be +found [here](https://github.com/webpack/media). + +## webpack documentation + +The content on [https://webpack.js.org/](https://webpack.js.org/) is available under [Creative Commons BY 4.0](https://creativecommons.org/licenses/by/4.0/) license meaning attribution is required should you use the content elsewhere. + +## webpack code samples + +The code samples use [CC0 1.0 Universal (CC0 1.0) (Public Domain)](https://creativecommons.org/publicdomain/zero/1.0/) and you are free to use them as you like. diff --git a/src/content/api/_api_all.md b/src/content/api/_api_all.md new file mode 100644 index 000000000000..d54e6da2b86f --- /dev/null +++ b/src/content/api/_api_all.md @@ -0,0 +1,3189 @@ + + +# Compiler Hooks + +The `Compiler` module is the main engine that creates a compilation instance +with all the options passed through the [CLI](/api/cli) or [Node API](/api/node). It extends the +`Tapable` class in order to register and call plugins. Most user facing plugins +are first registered on the `Compiler`. + +T> This module is exposed as `webpack.Compiler` and can be used directly. See +[this example](https://github.com/pksjce/webpack-internal-examples/tree/master/compiler-example) +for more information. + +When developing a plugin for webpack, you might want to know where each hook is called. To learn this, search for `hooks.<hook name>.call` across the webpack source + + +## Watching + +The `Compiler` supports [watching](/api/node/#watching) which monitors the file +system and recompiles as files change. When in watch mode, the compiler will +emit the additional events such as `watchRun`, `watchClose`, and `invalid`. +This is typically used in [development](/guides/development), usually under +the hood of tools like `webpack-dev-server`, so that the developer doesn't +need to re-compile manually every time. Watch mode can also be entered via the +[CLI](/api/cli/#watch-options). + + +## Hooks + +The following lifecycle hooks are exposed by the `compiler` and can be accessed +as such: + +``` js +compiler.hooks.someHook.tap(/* ... */); +``` + +Depending on the hook type, `tapAsync` and `tapPromise` may also be available. + +For the description of hook types, see [the Tapable docs](https://github.com/webpack/tapable#hook-types). + + +### `entryOption` + +`SyncBailHook` + +Executes a plugin after [the `entry` configuration](https://webpack.js.org/configuration/entry-context/#entry) from webpack options has been processed. + + +### `afterPlugins` + +`SyncHook` + +Runs a plugin after setting up initial set of plugins. + +Parameters: `compiler` + + +### `afterResolvers` + +`SyncHook` + +Executes a plugin after resolver setup is complete. + +Parameters: `compiler` + + +### `environment` + +`SyncHook` + +Runs a plugin before the environment is prepared. + + +### `afterEnvironment` + +`SyncHook` + +Executes a plugin a environment setup is complete. + + +### `beforeRun` + +`AsyncSeriesHook` + +Adds a hook right before `compiler.run()` is executed. + +Parameters: `compiler` + + +### `run` + +`AsyncSeriesHook` + +Hook into the compiler before it begins reading records. + +Parameters: `compiler` + + +### `watchRun` + +`AsyncSeriesHook` + +Executes a plugin during watch mode after a new compilation is triggered +but before the compilation is actually started. + +Parameters: `compiler` + + +### `normalModuleFactory` + +`SyncHook` + +Runs a plugin after a `NormalModuleFactory` is created. + +Parameters: `normalModuleFactory` + + +### `contextModuleFactory` + +Runs a plugin after a `ContextModuleFactory` is created. + +Parameters: `contextModuleFactory` + + +### `beforeCompile` + +`AsyncSeriesHook` + +Executes a plugin after compilation parameters are created. + +Parameters: `compilationParams` + + +### `compile` + +`SyncHook` + +Hook into the compiler before a new compilation is created. + +Parameters: `compilationParams` + + +### `thisCompilation` + +`SyncHook` + +Executed before emitting the `compilation` event (see below). + +Parameters: `compilation` + + +### `compilation` + +`SyncHook` + +Runs a plugin after a compilation has been created. + +Parameters: `compilation` + + +### `make` + +`AsyncParallelHook` + +... + +Parameters: `compilation` + + +### `afterCompile` + +`AsyncSeriesHook` + +... + +Parameters: `compilation` + + +### `shouldEmit` + +`SyncBailHook` + +Can return true/false at this point + +Parameters: `compilation` + + +### `emit` + +`AsyncSeriesHook` + +Before emitting assets to output dir + +Parameters: `compilation` + + +### `afterEmit` + +`AsyncSeriesHook` + +After emitting assets to output dir + +Parameters: `compilation` + + +### `done` + +`AsyncSeriesHook` + +Compilation has completed. + +Parameters: `stats` + + +### `failed` + +`SyncHook` + +Compilation has failed. + +Parameters: `error` + + +### `invalid` + +`SyncHook` + +Watch compilation has been invalidated. + +Parameters: `fileName`, `changeTime` + + +### `watchClose` + +`SyncHook` + +Watch mode has stopped. + + +# Introduction + +A variety of interfaces are available to customize the compilation process. +Some features overlap between interfaces, e.g. a configuration option may be +available via a CLI flag, while others exist only through a single interface. +The following high-level information should get you started. + + +## CLI + +The Command Line Interface (CLI) to configure and interact with your build. It +is especially useful in the case of early prototyping and profiling. For the +most part, the CLI is simply used to kick off the process using a configuration +file and a few flags (e.g. `--env`). + +[Learn more about the CLI!](/api/cli) + + +## Module + +When processing modules with webpack, it is important to understand the +different module syntaxes -- specifically the [methods](/api/module-methods) +and [variables](/api/module-variables) -- that are supported. + +[Learn more about modules!](/api/module-methods) + + +## Node + +While most users can get away with just using the CLI along with a +configuration file, more fine-grained control of the compilation can be +achieved via the Node interface. This includes passing multiple configurations, +programmatically running or watching, and collecting stats. + +[Learn more about the Node API!](/api/node) + + +## Loaders + +Loaders are transformations that are applied to the source code of a module. +They are written as functions that accept source code as a parameter and return +a new version of that code with transformations applied. + +[Learn more about loaders!](/api/loaders) + + +## Plugins + +The plugin interface allows users to tap directly into the compilation process. +Plugins can register handlers on lifecycle hooks that run at different points +throughout a compilation. When each hook is executed, the plugin will have full +access to the current state of the compilation. + +[Learn more about plugins!](/api/plugins) + + +# Command Line Interface + +For proper usage and easy distribution of this configuration, webpack can be configured with `webpack.config.js`. Any parameters sent to the CLI will map to a corresponding parameter in the config file. + +Read the [installation guide](/guides/installation) if you don't already have webpack and CLI installed. + + +## Usage with config file + +```sh +webpack [--config webpack.config.js] +``` + +See [configuration](/configuration) for the options in the configuration file. + + +## Usage without config file + +```sh +webpack <entry> [<entry>] -o <output> +``` + +__`<entry>`__ + +A filename or a set of named filenames which act as the entry point to build your project. You can pass multiple entries (every entry is loaded on startup). If you pass a pair in the form `<name>=<request>` you can create an additional entry point. It will be mapped to the configuration option `entry`. + +__`<output>`__ + +A path and filename for the bundled file to be saved in. It will be mapped to the configuration options `output.path` and `output.filename`. + +__Example__ + +If your project structure is as follows - + +```bash +. +├── dist +├── index.html +└── src + ├── index.js + ├── index2.js + └── others.js +``` + +```bash +webpack src/index.js -o dist/bundle.js +``` + +This will bundle your source code with entry as `index.js` and the output bundle file will have a path of `dist` and the filename will be `bundle.js` + +```bash + | Asset | Size | Chunks | Chunk Names | + |-----------|---------|-------------|-------------| + | bundle.js | 1.54 kB | 0 [emitted] | index | + [0] ./src/index.js 51 bytes {0} [built] + [1] ./src/others.js 29 bytes {0} [built] +``` + +```bash +webpack index=./src/index.js entry2=./src/index2.js dist/bundle.js +``` + +This will form the bundle with both the files as separate entry points. + +```bash + | Asset | Size | Chunks | Chunk Names | + |-----------|---------|---------------|---------------| + | bundle.js | 1.55 kB | 0,1 [emitted] | index, entry2 | + [0] ./src/index.js 51 bytes {0} [built] + [0] ./src/index2.js 54 bytes {1} [built] + [1] ./src/others.js 29 bytes {0} {1} [built] +``` + + +### Common Options + +W> Note that Command Line Interface has a higher precedence for the arguments you use it with than your configuration file. For instance, if you pass [`--mode="production"`](/concepts/mode/#usage) to webpack CLI and your configuration file uses `development`, `production` will be used. + +__List all of the options available on the cli__ + +```bash +webpack --help +webpack -h +``` + +__Build source using a config file__ + +Specifies a different [configuration](/configuration) file to pick up. Use this if you want to specify something different than `webpack.config.js`, which is the default. + +```bash +webpack --config example.config.js +``` + +__Print result of webpack as a JSON__ + +```bash +webpack --json +webpack --json > stats.json +``` + +In every other case, webpack prints out a set of stats showing bundle, chunk and timing details. Using this option the output can be a JSON object. This response is accepted by webpack's [analyse tool](https://webpack.github.io/analyse/), or chrisbateman's [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/), or th0r's [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). The analyse tool will take in the JSON and provide all the details of the build in graphical form. + +### Environment Options + +When the webpack configuration [exports a function](/configuration/configuration-types#exporting-a-function), an "environment" may be passed to it. + +```bash +webpack --env.production # sets env.production == true +webpack --env.platform=web # sets env.platform == "web" +``` + +The `--env` argument accepts various syntaxes: + +Invocation | Resulting environment +---------------------------------------- | --------------------------- +`webpack --env prod` | `"prod"` +`webpack --env.prod` | `{ prod: true }` +`webpack --env.prod=1` | `{ prod: 1 }` +`webpack --env.prod=foo` | `{ prod: "foo" }` +`webpack --env.prod --env.min` | `{ prod: true, min: true }` +`webpack --env.prod --env min` | `[{ prod: true }, "min"]` +`webpack --env.prod=foo --env.prod=bar` | `{prod: [ "foo", "bar" ]}` + +T> See the [environment variables](/guides/environment-variables) guide for more information on its usage. + +### Config Options + +Parameter | Explanation | Input type | Default +------------------------- | ------------------------------------------- | ---------- | ------------------ +`--config` | Path to the config file | string | webpack.config.js or webpackfile.js +`--config-register, -r` | Preload one or more modules before loading the webpack configuration | array | +`--config-name` | Name of the config to use | string | +`--env` | Environment passed to the config, when it is a function | | +`--mode` | Mode to use, either "development" or "production" | string | + +### Output Options + +This set of options allows you to manipulate certain [output](/configuration/output) parameters of your build. + +Parameter | Explanation | Input type | Default +------------------------- | ------------------------------------------- | ---------- | ------------------ +`--output-chunk-filename` | The output filename for additional chunks | string | filename with [id] instead of [name] or [id] prefixed +`--output-filename` | The output filename of the bundle | string | [name].js +`--output-jsonp-function` | The name of the JSONP function used for chunk loading | string | webpackJsonp +`--output-library` | Expose the exports of the entry point as library | string | +`--output-library-target` | The type for exposing the exports of the entry point as library | string | var +`--output-path` | The output path for compilation assets | string | Current directory +`--output-pathinfo` | Include a comment with the request for every dependency | boolean | false +`--output-public-path` | The public path for the assets | string | / +`--output-source-map-filename` | The output filename for the SourceMap | string | [name].map or [outputFilename].map +`--build-delimiter` | Display custom text after build output | string | Default string is null. You could provide a string such as `=== Build done ===` + + +#### Example Usage + +```bash +webpack index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' + +| Asset | Size | Chunks | Chunk Names | +|--------------------------------------|---------|-------------|---------------| +| index2740fdca26e9348bedbec.bundle.js | 2.6 kB | 0 [emitted] | index2 | +| index740fdca26e9348bedbec.bundle.js | 2.59 kB | 1 [emitted] | index | + [0] ./src/others.js 29 bytes {0} {1} [built] + [1] ./src/index.js 51 bytes {1} [built] + [2] ./src/index2.js 54 bytes {0} [built] +``` + +```bash +webpack.js index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' --devtool source-map --output-source-map-filename='[name]123.map' + +| Asset | Size | Chunks | Chunk Names | +|--------------------------------------|---------|-------------|---------------| +| index2740fdca26e9348bedbec.bundle.js | 2.76 kB | 0 [emitted] | index2 | +| index740fdca26e9348bedbec.bundle.js | 2.74 kB | 1 [emitted] | index | +| index2123.map | 2.95 kB | 0 [emitted] | index2 | +| index123.map | 2.95 kB | 1 [emitted] | index | + [0] ./src/others.js 29 bytes {0} {1} [built] + [1] ./src/index.js 51 bytes {1} [built] + [2] ./src/index2.js 54 bytes {0} [built] +``` + + +### Debug Options + +This set of options allows you to better debug the application containing assets compiled with webpack + +Parameter | Explanation | Input type | Default value +------------ | ------------------------------------------------ | ---------- | ------------- +`--debug` | Switch loaders to debug mode | boolean | false +`--devtool` | Define [source map type](/configuration/devtool/) for the bundled resources | string | - +`--progress` | Print compilation progress in percentage | boolean | false +`--display-error-details` | Display details about errors | boolean | false + +### Module Options + +These options allow you to bind [modules](/configuration/module/) as allowed by webpack + +Parameter | Explanation | Usage +-------------------- | -------------------------------------- | ---------------- +`--module-bind` | Bind a file extension to a loader | `--module-bind js=babel-loader` +`--module-bind-post` | Bind a file extension to a post loader | +`--module-bind-pre` | Bind a file extension to a pre loader | + + +### Watch Options + +These options makes the build [watch](/configuration/watch/) for changes in files of the dependency graph and perform the build again. + +Parameter | Explanation +------------------------- | ---------------------- +`--watch`, `-w` | Watch the filesystem for changes +`--watch-aggregate-timeout` | Timeout for gathering changes while watching +`--watch-poll` | The polling interval for watching (also enable polling) +`--watch-stdin`, `--stdin` | Exit the process when stdin is closed + + +### Optimize Options + +These options allow you to manipulate optimisations for a production build using webpack + +Parameter | Explanation | Plugin Used +--------------------------- | -------------------------------------------------------|---------------------- +`--optimize-max-chunks` | Try to keep the chunk count below a limit | [LimitChunkCountPlugin](/plugins/limit-chunk-count-plugin) +`--optimize-min-chunk-size` | Try to keep the chunk size above a limit | [MinChunkSizePlugin](/plugins/min-chunk-size-plugin) +`--optimize-minimize` | Minimize javascript and switches loaders to minimizing | [TerserPlugin](/plugins/terser-webpack-plugin/) & [LoaderOptionsPlugin](/plugins/loader-options-plugin/) + + +### Resolve Options + +These allow you to configure the webpack [resolver](/configuration/resolve/) with aliases and extensions. + +Parameter | Explanation | Example +---------------------- | ------------------------------------------------------- | ------------- +`--resolve-alias` | Setup a module alias for resolving | --resolve-alias jquery-plugin=jquery.plugin +`--resolve-extensions` | Setup extensions that should be used to resolve modules | --resolve-extensions .es6 .js .ts +`--resolve-loader-alias` | Minimize javascript and switches loaders to minimizing | + + +### Stats Options + +These options allow webpack to display various [stats](/configuration/stats/) and style them differently in the console output. + +Parameter | Explanation | Type +-------------------------------- | ------------------------------------------------------------------ | ------- +`--color`, `--colors` | Force colors on the console [default: enabled for TTY output only] | boolean +`--no-color`, `--no-colors` | Force no colors on the console | boolean +`--display` | Select [display preset](/configuration/stats) (verbose, detailed, normal, minimal, errors-only, none; since webpack 3.0.0) | string +`--display-cached` | Display also cached modules in the output | boolean +`--display-cached-assets` | Display also cached assets in the output | boolean +`--display-chunks` | Display chunks in the output | boolean +`--display-depth` | Display distance from entry point for each module | boolean +`--display-entrypoints` | Display entry points in the output | boolean +`--display-error-details` | Display details about errors | boolean +`--display-exclude` | Exclude modules in the output | boolean +`--display-max-modules` | Sets the maximum number of visible modules in output | number +`--display-modules` | Display even excluded modules in the output | boolean +`--display-optimization-bailout` | Scope hoisting fallback trigger (since webpack 3.0.0) | boolean +`--display-origins` | Display origins of chunks in the output | boolean +`--display-provided-exports` | Display information about exports provided from modules | boolean +`--display-reasons` | Display reasons about module inclusion in the output | boolean +`--display-used-exports` | Display information about used exports in modules (Tree Shaking) | boolean +`--hide-modules` | Hides info about modules | boolean +`--sort-assets-by` | Sorts the assets list by property in asset | string +`--sort-chunks-by` | Sorts the chunks list by property in chunk | string +`--sort-modules-by` | Sorts the modules list by property in module | string +`--verbose` | Show more details | boolean + + +### Advanced Options + +Parameter | Explanation | Usage +----------------- | ---------------------------------------- | ----- +`--bail` | Abort the compilation on first error | +`--cache` | Enable in memory caching [Enabled by default for watch] | `--cache=false` +`--define` | Define any free variable, see [shimming](/guides/shimming) | `--define process.env.NODE_ENV="'development'"` +`--hot` | Enables [Hot Module Replacement](/concepts/hot-module-replacement) | `--hot=true` +`--labeled-modules` | Enables labeled modules [Uses LabeledModulesPlugin] | +`--plugin` | Load this [plugin](/configuration/plugins/) | +`--prefetch` | Prefetch the particular file | `--prefetch=./files.js` +`--provide` | Provide these modules as globals, see [shimming](/guides/shimming) | `--provide jQuery=jquery` +`--records-input-path` | Path to the records file (reading) | +`--records-output-path` | Path to the records file (writing) | +`--records-path` | Path to the records file | +`--target` | The [targeted](/configuration/target/) execution environment | `--target='node'` + +### Shortcuts + +Shortcut | Replaces +---------|---------------------------- +-d | `--debug --devtool cheap-module-eval-source-map --output-pathinfo` +-p | `--optimize-minimize --define process.env.NODE_ENV="production"`, see [building for production](/guides/production) + +### Profiling + +The `--profile` option captures timing information for each step of the compilation and includes this in the output. + +```bash +webpack --profile + +⋮ +[0] ./src/index.js 90 bytes {0} [built] + factory:22ms building:16ms = 38ms +``` + +For each module, the following details are included in the output as applicable: + +- `factory`: time to collect module metadata (e.g. resolving the filename) +- `building`: time to build the module (e.g. loaders and parsing) +- `dependencies`: time to identify and connect the module’s dependencies + +Paired with `--progress`, `--profile` gives you an in depth idea of which step in the compilation is taking how long. This can help you optimise your build in a more informed manner. + +```bash +webpack --progress --profile + +30ms building modules +1ms sealing +1ms optimizing +0ms basic module optimization +1ms module optimization +1ms advanced module optimization +0ms basic chunk optimization +0ms chunk optimization +1ms advanced chunk optimization +0ms module and chunk tree optimization +1ms module reviving +0ms module order optimization +1ms module id optimization +1ms chunk reviving +0ms chunk order optimization +1ms chunk id optimization +10ms hashing +0ms module assets processing +13ms chunk assets processing +1ms additional chunk assets processing +0ms recording +0ms additional asset processing +26ms chunk asset optimization +1ms asset optimization +6ms emitting +⋮ +``` + + +# Compilation Hooks + +The `Compilation` module is used by the `Compiler` to create new compilations +(or builds). A `compilation` instance has access to all modules and their +dependencies (most of which are circular references). It is the literal +compilation of all the modules in the dependency graph of an application. +During the compilation phase, modules are loaded, sealed, optimized, chunked, +hashed and restored. + +The `Compilation` class also extends `Tapable` and provides the following +lifecycle hooks. They can be tapped the same way as compiler hooks: + +``` js +compilation.hooks.someHook.tap(/* ... */); +``` + +As with the `compiler`, `tapAsync` and `tapPromise` may also be available +depending on the type of hook. + + +### `buildModule` + +`SyncHook` + +Triggered before a module build has started. + +Parameters: `module` + + +### `rebuildModule` + +`SyncHook` + +Fired before rebuilding a module. + +Parameters: `module` + + +### `failedModule` + +`SyncHook` + +Run when a module build has failed. + +Parameters: `module` `error` + + +### `succeedModule` + +`SyncHook` + +Executed when a module has been built successfully. + +Parameters: `module` + + +### `finishModules` + +`SyncHook` + +All modules have been built. + +Parameters: `modules` + + +### `finishRebuildingModule` + +`SyncHook` + +A module has been rebuilt. + +Parameters: `module` + + +### `seal` + +`SyncHook` + +Fired when the compilation stops accepting new modules. + + +### `unseal` + +`SyncHook` + +Fired when a compilation begins accepting new modules. + + +### `optimizeDependenciesBasic` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeDependencies` + +`SyncBailHook` + +Fired at the beginning of dependency optimization. + +Parameters: `modules` + + +### `optimizeDependenciesAdvanced` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `afterOptimizeDependencies` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimize` + +`SyncHook` + +Triggered at the beginning of the optimization phase. + + +### `optimizeModulesBasic` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeModules` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeModulesAdvanced` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `afterOptimizeModules` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimizeChunksBasic` + +`SyncBailHook` + +... + +Parameters: `chunks` + + +### `optimizeChunks` + +`SyncBailHook` + +Optimize the chunks. + +Parameters: `chunks` + + +### `optimizeChunksAdvanced` + +`SyncBailHook` + +... + +Parameters: `chunks` + + +### `afterOptimizeChunks` + +`SyncHook` + +Fired after chunk optimization has completed. + +Parameters: `chunks` + + +### `optimizeTree` + +`AsyncSeriesHook` + +Optimize the dependency tree asynchronously. + +Parameters: `chunks` `modules` + + +### `afterOptimizeTree` + +`SyncHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModulesBasic` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModules` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModulesAdvanced` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `afterOptimizeChunkModules` + +`SyncHook` + +... + +Parameters: `chunks` `modules` + + +### `shouldRecord` + +`SyncBailHook` + +... + + +### `reviveModules` + +`SyncHook` + +Restore module information from records. + +Parameters: `modules` `records` + + +### `optimizeModuleOrder` + +`SyncHook` + +Sort the modules in from most to least important. + +Parameters: `modules` + + +### `advancedOptimizeModuleOrder` + +`SyncHook` + +... + +Parameters: `modules` + + +### `beforeModuleIds` + +`SyncHook` + +... + +Parameters: `modules` + + +### `moduleIds` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimizeModuleIds` + +`SyncHook` + +... + +Parameters: `chunks` + + +### `afterOptimizeModuleIds` + +`SyncHook` + +... + +Parameters: `chunks` + + +### `reviveChunks` + +`SyncHook` + +Restore chunk information from records. + +Parameters: `modules` `records` + + +### `optimizeChunkOrder` + +`SyncHook` + +Sort the chunks in from most to least important. + +Parameters: `chunks` + + +### `beforeOptimizeChunkIds` + +`SyncHook` + +Fired before chunk `id` optimization. + +Parameters: `chunks` + + +### `optimizeChunkIds` + +`SyncHook` + +Optimize the `id` of each chunk. + +Parameters: `chunks` + + +### `afterOptimizeChunkIds` + +`SyncHook` + +Triggered after chunk `id` optimization has finished. + +Parameters: `chunks` + + +### `recordModules` + +`SyncHook` + +Store module info to the records. + +Parameters: `modules` `records` + + +### `recordChunks` + +`SyncHook` + +Store chunk info to the records. + +Parameters: `chunks` `records` + + +### `beforeHash` + +`SyncHook` + +Before the compilation is hashed. + + +### `afterHash` + +`SyncHook` + +After the compilation is hashed. + + +### `recordHash` + +`SyncHook` + +... + +Parameters: `records` + + +### `record` + +`SyncHook` + +Store information about the `compilation` to the `records`. + +Parameters: `compilation` `records` + + +### `beforeModuleAssets` + +`SyncHook` + +... + + +### `shouldGenerateChunkAssets` + +`SyncBailHook` + +... + + +### `beforeChunkAssets` + +`SyncHook` + +Before creating the chunk assets. + + +### `additionalChunkAssets` + +`SyncHook` + +Create additional assets for the chunks. + +Parameters: `chunks` + + +### `records` + +`SyncHook` + +... + +Parameters: `compilation` `records` + + +### `additionalAssets` + +`AsyncSeriesHook` + +Create additional assets for the compilation. This hook can be used to download +an image, for example: + +``` js +compilation.hooks.additionalAssets.tapAsync('MyPlugin', callback => { + download('https://img.shields.io/npm/v/webpack.svg', function(resp) { + if(resp.status === 200) { + compilation.assets['webpack-version.svg'] = toAsset(resp); + callback(); + } else { + callback(new Error('[webpack-example-plugin] Unable to download the image')); + } + }); +}); +``` + + +### `optimizeChunkAssets` + +`AsyncSeriesHook` + +Optimize any chunk assets. The assets are stored in `compilation.assets`. A +`Chunk` has a property `files` which points to all files created by a chunk. +Any additional chunk assets are stored in `compilation.additionalChunkAssets`. + +Parameters: `chunks` + +Here's an example that simply adds a banner to each chunk. + +``` js +compilation.hooks + .optimizeChunkAssets + .tapAsync('MyPlugin', (chunks, callback) => { + chunks.forEach(chunk => { + chunk.files.forEach(file => { + compilation.assets[file] = new ConcatSource( + '\/**Sweet Banner**\/', + '\n', + compilation.assets[file] + ); + }); + }); + + callback(); + }); +``` + + +### `afterOptimizeChunkAssets` + +`SyncHook` + +The chunk assets have been optimized. + +Parameters: `chunks` + +Here's an example plugin from [@boopathi](https://github.com/boopathi) that outputs exactly what went into each chunk. + +``` js +compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', chunks => { + chunks.forEach(chunk => { + console.log({ + id: chunk.id, + name: chunk.name, + includes: chunk.modules.map(module => module.request) + }); + }); +}); +``` + + +### `optimizeAssets` + +`AsyncSeriesHook` + +Optimize all assets stored in `compilation.assets`. + +Parameters: `assets` + + +### `afterOptimizeAssets` + +`SyncHook` + +The assets has been optimized. + +Parameters: `assets` + + +### `needAdditionalSeal` + +`SyncBailHook` + +... + + +### `afterSeal` + +`AsyncSeriesHook` + +... + + +### `chunkHash` + +`SyncHook` + +... + +Parameters: `chunk` `chunkHash` + + +### `moduleAsset` + +`SyncHook` + +An asset from a module was added to the compilation. + +Parameters: `module` `filename` + + +### `chunkAsset` + +`SyncHook` + +An asset from a chunk was added to the compilation. + +Parameters: `chunk` `filename` + + +### `assetPath` + +`SyncWaterfallHook` + +... + +Parameters: `filename` `data` + + +### `needAdditionalPass` + +`SyncBailHook` + +... + + +### `childCompiler` + +`SyncHook` + +... + +Parameters: `childCompiler` `compilerName` `compilerIndex` + + +### `normalModuleLoader` + +`SyncHook` + +The normal module loader is the function that actually loads all the modules +in the module graph (one-by-one). + +Parameters: `loaderContext` `module` + +### `dependencyReference` + +`SyncWaterfallHook` + +`Compilation.hooks.dependencyReference(depRef, dependency, module)` allows to change the references reported by dependencies. + +Parameters: `depRef` `dependency` `module` + + +# Module Methods + +This section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including [ES6](https://en.wikipedia.org/wiki/ECMAScript#6th_Edition_-_ECMAScript_2015), [CommonJS](https://en.wikipedia.org/wiki/CommonJS), and [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition). + +W> While webpack supports multiple module syntaxes, we recommend following a single syntax for consistency and to avoid odd behaviors/bugs. Here's [one example](https://github.com/webpack/webpack.js.org/issues/552) of mixing ES6 and CommonJS, however there are surely others. + + +## ES6 (Recommended) + +Version 2 of webpack supports ES6 module syntax natively, meaning you can use `import` and `export` without a tool like babel to handle this for you. Keep in mind that you will still probably need babel for other ES6+ features. The following methods are supported by webpack: + + +### `import` + +Statically `import` the `export`s of another module. + +``` javascript +import MyModule from './my-module.js'; +import { NamedExport } from './other-module.js'; +``` + +W> The keyword here is __statically__. Normal `import` statement cannot be used dynamically within other logic or contain variables. See the [spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) for more information and `import()` below for dynamic usage. + + +### `export` + +Export anything as a `default` or named export. + +``` javascript +// Named exports +export var Count = 5; +export function Multiply(a, b) { + return a * b; +} + +// Default export +export default { + // Some data... +}; +``` + + +### `import()` + +`import('path/to/module') -> Promise` + +Dynamically load modules. Calls to `import()` are treated as split points, meaning the requested module and it's children are split out into a separate chunk. + +T> The [ES2015 Loader spec](https://whatwg.github.io/loader/) defines `import()` as method to load ES2015 modules dynamically on runtime. + +``` javascript +if ( module.hot ) { + import('lodash').then(_ => { + // Do something with lodash (a.k.a '_')... + }); +} +``` + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +The spec for `import` doesn't allow control over the chunk's name or other properties as "chunks" are only a concept within webpack. Luckily webpack allows some special parameters via comments so as to not break the spec: + +``` js +// Single target +import( + /* webpackChunkName: "my-chunk-name" */ + /* webpackMode: "lazy" */ + 'module' +); + +// Multiple possible targets +import( + /* webpackInclude: /\.json$/ */ + /* webpackExclude: /\.noimport\.json$/ */ + /* webpackChunkName: "my-chunk-name" */ + /* webpackMode: "lazy" */ + `./locale/${language}` +); +``` + +```js +import(/* webpackIgnore: true */ 'ignored-module.js'); +``` + +`webpackIgnore`: Disables dynamic import parsing when set to `true`. + +W> Note that setting `webpackIgnore` to `true` opts out of code splitting. + +`webpackChunkName`: A name for the new chunk. Since webpack 2.6.0, the placeholders `[index]` and `[request]` are supported within the given string to an incremented number or the actual resolved filename respectively. + +`webpackMode`: Since webpack 2.6.0, different modes for resolving dynamic imports can be specified. The following options are supported: + +- `"lazy"` (default): Generates a lazy-loadable chunk for each `import()`ed module. +- `"lazy-once"`: Generates a single lazy-loadable chunk that can satisfy all calls to `import()`. The chunk will be fetched on the first call to `import()`, and subsequent calls to `import()` will use the same network response. Note that this only makes sense in the case of a partially dynamic statement, e.g. ``import(`./locales/${language}.json`)``, where there are multiple module paths that could potentially be requested. +- `"eager"`: Generates no extra chunk. All modules are included in the current chunk and no additional network requests are made. A `Promise` is still returned but is already resolved. In contrast to a static import, the module isn't executed until the call to `import()` is made. +- `"weak"`: Tries to load the module if the module function has already been loaded in some other way (i. e. another chunk imported it or a script containing the module was loaded). A `Promise` is still returned but, only successfully resolves if the chunks are already on the client. If the module is not available, the `Promise` is rejected. A network request will never be performed. This is useful for universal rendering when required chunks are always manually served in initial requests (embedded within the page), but not in cases where app navigation will trigger an import not initially served. + +T> Note that all options can be combined like so `/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */`. This is wrapped in a JavaScript object and executed using [node VM](https://nodejs.org/dist/latest-v8.x/docs/api/vm.html). You do not need to add curly brackets. + +`webpackInclude`: A regular expression that will be matched against during import resolution. Only modules that match __will be bundled__. + +`webpackExclude`: A regular expression that will be matched against during import resolution. Any module that matches __will not be bundled__. + +T> Note that `webpackInclude` and `webpackExclude` options do not interfere with the prefix. eg: `./locale`. + +W> Fully dynamic statements, such as `import(foo)`, __will fail__ because webpack requires at least some file location information. This is because `foo` could potentially be any path to any file in your system or project. The `import()` must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files. + +W> Every module that could potentially be requested on an `import()` call is included. For example, ``import(`./locale/${language}.json`)`` will cause every `.json` file in the `./locale` directory to be bundled into the new chunk. At run time, when the variable `language` has been computed, any file like `english.json` or `german.json` will be available for consumption. Using the `webpackInclude` and `webpackExclude` options allows us to add regex patterns that reduce the files that webpack will bundle for this import. + +W> The use of `System.import` in webpack [did not fit the proposed spec](https://github.com/webpack/webpack/issues/2163), so it was deprecated in webpack [2.1.0-beta.28](https://github.com/webpack/webpack/releases/tag/v2.1.0-beta.28) in favor of `import()`. + + +## CommonJS + +The goal of CommonJS is to specify an ecosystem for JavaScript outside the browser. The following CommonJS methods are supported by webpack: + + +### `require` + +``` javascript +require(dependency: String); +``` + +Synchronously retrieve the exports from another module. The compiler will ensure that the dependency is available in the output bundle. + +``` javascript +var $ = require('jquery'); +var myModule = require('my-module'); +``` + +W> Using it asynchronously may not have the expected effect. + + +### `require.resolve` + +``` javascript +require.resolve(dependency: String); +``` + +Synchronously retrieve a module's ID. The compiler will ensure that the dependency is available in the output bundle. See [`module.id`](/api/module-variables#module-id-commonjs-) for more information. + +W> Module ID is a number in webpack (in contrast to NodeJS where it is a string -- the filename). + + +### `require.cache` + +Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. + +W> This is only needed in rare cases for compatibility! + +``` javascript +var d1 = require('dependency'); +require('dependency') === d1; +delete require.cache[require.resolve('dependency')]; +require('dependency') !== d1; +``` + +``` javascript +// in file.js +require.cache[module.id] === module; +require('./file.js') === module.exports; +delete require.cache[module.id]; +require.cache[module.id] === undefined; +require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow +require.cache[module.id] !== module; +``` + + +### `require.ensure` + +W> `require.ensure()` is specific to webpack and superseded by `import()`. + +<!-- eslint-skip --> + +```js +require.ensure( + dependencies: String[], + callback: function(require), + errorCallback: function(error), + chunkName: String +) +``` + +Split out the given `dependencies` to a separate bundle that that will be loaded asynchronously. When using CommonJS module syntax, this is the only way to dynamically load dependencies. Meaning, this code can be run within execution, only loading the `dependencies` if certain conditions are met. + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `require.ensure` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +``` javascript +var a = require('normal-dep'); + +if ( module.hot ) { + require.ensure(['b'], function(require) { + var c = require('c'); + + // Do something special... + }); +} +``` + +The following parameters are supported in the order specified above: + +- `dependencies`: An array of strings declaring all modules required for the code in the `callback` to execute. +- `callback`: A function that webpack will execute once the dependencies are loaded. An implementation of the `require` function is sent as a parameter to this function. The function body can use this to further `require()` modules it needs for execution. +- `errorCallback`: A function that is executed when webpack fails to load the dependencies. +- `chunkName`: A name given to the chunk created by this particular `require.ensure()`. By passing the same `chunkName` to various `require.ensure()` calls, we can combine their code into a single chunk, resulting in only one bundle that the browser must load. + +W> Although the implementation of `require` is passed as an argument to the `callback` function, using an arbitrary name e.g. `require.ensure([], function(request) { request('someModule'); })` isn't handled by webpack's static parser. Use `require` instead, e.g. `require.ensure([], function(require) { require('someModule'); })`. + + + +## AMD + +Asynchronous Module Definition (AMD) is a JavaScript specification that defines an interface for writing and loading modules. The following AMD methods are supported by webpack: + + +### `define` (with factory) + +<!-- eslint-skip --> + +```js +define([name: String], [dependencies: String[]], factoryMethod: function(...)) +``` + +If `dependencies` are provided, `factoryMethod` will be called with the exports of each dependency (in the same order). If `dependencies` are not provided, `factoryMethod` is called with `require`, `exports` and `module` (for compatibility!). If this function returns a value, this value is exported by the module. The compiler ensures that each dependency is available. + +W> Note that webpack ignores the `name` argument. + +``` javascript +define(['jquery', 'my-module'], function($, myModule) { + // Do something with $ and myModule... + + // Export a function + return function doSomething() { + // ... + }; +}); +``` + +W> This CANNOT be used in an asynchronous function. + + +### `define` (with value) + +<!-- eslint-skip --> + +```js +define(value: !Function) +``` + +This will simply export the provided `value`. The `value` here can be anything except a function. + +``` javascript +define({ + answer: 42 +}); +``` + +W> This CANNOT be used in an async function. + + +### `require` (amd-version) + +<!-- eslint-skip --> + +```js +require(dependencies: String[], [callback: function(...)]) +``` + +Similar to `require.ensure`, this will split the given `dependencies` into a separate bundle that will be loaded asynchronously. The `callback` will be called with the exports of each dependency in the `dependencies` array. + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use AMD with older browsers (e.g. Internet Explorer 11), remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +``` javascript +require(['b'], function(b) { + var c = require('c'); +}); +``` + +W> There is no option to provide a chunk name. + + + +## Labeled Modules + +The internal `LabeledModulesPlugin` enables you to use the following methods for exporting and requiring within your modules: + + +### `export` label + +Export the given `value`. The label can occur before a function declaration or a variable declaration. The function name or variable name is the identifier under which the value is exported. + +<!-- eslint-skip --> + +```js +export: var answer = 42; +export: function method(value) { + // Do something... +}; +``` + +W> Using it in an async function may not have the expected effect. + + +### `require` label + +Make all exports from the dependency available in the current scope. The `require` label can occur before a string. The dependency must export values with the `export` label. CommonJS or AMD modules cannot be consumed. + +__some-dependency.js__ + +<!-- eslint-skip --> + +```js +export: var answer = 42; +export: function method(value) { + // Do something... +}; +``` + +<!-- eslint-skip --> + +```js +require: 'some-dependency'; +console.log(answer); +method(...); +``` + + + +## Webpack + +Aside from the module syntaxes described above, webpack also allows a few custom, webpack-specific methods: + + +### `require.context` + +<!-- eslint-skip --> + +```js +require.context( + directory: String, + includeSubdirs: Boolean /* optional, default true */, + filter: RegExp /* optional, default /^\.\/.*$/, any file */, + mode: String /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */ +) +``` + +Specify a whole group of dependencies using a path to the `directory`, an option to `includeSubdirs`, a `filter` for more fine grained control of the modules included, and a `mode` to define the way how loading will work. Underlying modules can then be easily resolved later on: + +```javascript +var context = require.context('components', true, /\.html$/); +var componentA = context.resolve('componentA'); +``` + +If `mode` is specified as "lazy", the underlying modules will be loaded asynchronously: + +```javascript +var context = require.context('locales', true, /\.json$/, 'lazy'); +context('localeA').then(locale => { + // do something with locale +}); +``` + +The full list of available modes and its behavior is described in [`import()`](#import-) documentation. + +### `require.include` + +<!-- eslint-skip --> + +```js +require.include(dependency: String) +``` + +Include a `dependency` without executing it. This can be used for optimizing the position of a module in the output chunks. + +``` javascript +require.include('a'); +require.ensure(['a', 'b'], function(require) { /* ... */ }); +require.ensure(['a', 'c'], function(require) { /* ... */ }); +``` + +This will result in following output: + +- entry chunk: `file.js` and `a` +- anonymous chunk: `b` +- anonymous chunk: `c` + +Without `require.include('a')` it would be duplicated in both anonymous chunks. + + +### `require.resolveWeak` + +Similar to `require.resolve`, but this won't pull the `module` into the bundle. It's what is considered a "weak" dependency. + +``` javascript +if(__webpack_modules__[require.resolveWeak('module')]) { + // Do something when module is available... +} +if(require.cache[require.resolveWeak('module')]) { + // Do something when module was loaded before... +} + +// You can perform dynamic resolves ("context") +// just as with other require/import methods. +const page = 'Foo'; +__webpack_modules__[require.resolveWeak(`./page/${page}`)]; +``` + +T> `require.resolveWeak` is the foundation of _universal rendering_ (SSR + Code Splitting), as used in packages such as [react-universal-component](https://github.com/faceyspacey/react-universal-component). It allows code to render synchronously on both the server and initial page-loads on the client. It requires that chunks are manually served or somehow available. It's able to require modules without indicating they should be bundled into a chunk. It's used in conjunction with `import()` which takes over when user navigation triggers additional imports. + + +# Node.js API + +webpack provides a Node.js API which can be used directly in Node.js runtime. + +The Node.js API is useful in scenarios in which you need to customize the build or development process since all the reporting and error handling must be done manually and webpack only does the compiling part. For this reason the [`stats`](/configuration/stats) configuration options will not have any effect in the `webpack()` call. + + +## Installation + +To start using webpack Node.js API, first install webpack if you haven’t yet: + +``` bash +npm install --save-dev webpack +``` + +Then require the webpack module in your Node.js script: + +``` js +const webpack = require('webpack'); +``` + +Or if you prefer ES2015: + +``` js +import webpack from 'webpack'; +``` + + +## `webpack()` + +The imported `webpack` function is fed a webpack [Configuration Object](/configuration/) and runs the webpack compiler if a callback function is provided: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, [stats](#stats-object)) => { + if (err || stats.hasErrors()) { + // [Handle errors here](#error-handling) + } + // Done processing +}); +``` + +T> The `err` object __will not__ include compilation errors and those must be handled separately using `stats.hasErrors()` which will be covered in detail in [Error Handling](#error-handling) section of this guide. The `err` object will only contain webpack-related issues, such as misconfiguration, etc. + +T> You can provide the `webpack` function with an array of configurations. See +the [MultiCompiler](#multicompiler) section below for more information. + + +## Compiler Instance + +If you don’t pass the `webpack` runner function a callback, it will return a +webpack `Compiler` instance. This instance can be used to manually trigger the +webpack runner or have it build and watch for changes, much like the +[CLI](/api/cli/). The `Compiler` instance provides the following methods: + +- `.run(callback)` +- `.watch(watchOptions, handler)` + +Typically, only one master `Compiler` instance is created, although child +compilers can be created in order to delegate specific tasks. The `Compiler` is +ultimately just a function which performs bare minimum functionality to keep a +lifecycle running. It delegates all the loading, bundling, and writing work to +registered plugins. + +The `hooks` property on a `Compiler` instance is used to register a plugin to +any hook event in the `Compiler`'s lifecycle. The +[`WebpackOptionsDefaulter`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js) +and [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js) +utilities are used by webpack to configure its `Compiler` instance with all the +built-in plugins. + +The `run` method is then used to kickstart all compilation work. Upon +completion, the given `callback` function is executed. The final logging of +stats and errors should be done in this `callback` function. + +W> The API only supports a single concurrent compilation at a time. When using +`run`, wait for it to finish before calling `run` or `watch` again. When using +`watch`, call `close` and wait for it to finish before calling `run` or `watch` +again. Concurrent compilations will corrupt the output files. + + +## Run + +Calling the `run` method on the `Compiler` instance is much like the quick run +method mentioned above: + +``` js-with-links +const webpack = require("webpack"); + +const compiler = webpack({ + // [Configuration Object](/configuration/) +}); + +compiler.run((err, [stats](#stats-object)) => { + // ... +}); +``` + + +## Watching + +Calling the `watch` method, triggers the webpack runner, but then watches for +changes (much like CLI: `webpack --watch`), as soon as webpack detects a +change, runs again. Returns an instance of `Watching`. + +``` js +watch(watchOptions, callback); +``` + +``` js-with-links +const webpack = require("webpack"); + +const compiler = webpack({ + // [Configuration Object](/configuration/) +}); + +const watching = compiler.watch({ + // Example [watchOptions](/configuration/watch/#watchoptions) + aggregateTimeout: 300, + poll: undefined +}, (err, [stats](#stats-object)) => { + // Print watch/build result here... + console.log(stats); +}); +``` + +`Watching` options are covered in detail +[here](/configuration/watch/#watchoptions). + +W> Filesystem inaccuracies may trigger multiple builds for a single change. So, +in the example above, the `console.log` statement may fire multiple times for a +single modification. Users should expect this behavior and may check +`stats.hash` to see if the file hash has actually changed. + + +### Close `Watching` + +The `watch` method returns a `Watching` instance that exposes +`.close(callback)` method. Calling this method will end watching: + +``` js +watching.close(() => { + console.log('Watching Ended.'); +}); +``` + +W> It’s not allowed to watch or run again before the existing watcher has been +closed or invalidated. + + +### Invalidate `Watching` + +Using `watching.invalidate`, you can manually invalidate the current compiling +round, without stopping the watch process: + +``` js +watching.invalidate(); +``` + + +## Stats Object + +The `stats` object that is passed as a second argument of the +[`webpack()`](#webpack-) callback, is a good source of information about the +code compilation process. It includes: + +- Errors and Warnings (if any) +- Timings +- Module and Chunk information + +The [webpack CLI](/api/cli) uses this information to display nicely formatted +output in your console. + +T> When using the [`MultiCompiler`](/api/plugins/compiler#multicompiler), a +`MultiStats` instance is returned that fulfills the same interface as `stats`, +i.e. the methods described below. + +This `stats` object exposes the following methods: + + +### `stats.hasErrors()` + +Can be used to check if there were errors while compiling. Returns `true` or +`false`. + + +### `stats.hasWarnings()` + +Can be used to check if there were warnings while compiling. Returns `true` or +`false`. + + +### `stats.toJson(options)` + +Returns compilation information as a JSON object. `options` can be either a +string (a preset) or an object for more granular control: + +``` js-with-links +stats.toJson("minimal"); // [more options: "verbose", etc](/configuration/stats). +``` + +``` js +stats.toJson({ + assets: false, + hash: true +}); +``` + +All available options and presets are described in the stats [documentation](/configuration/stats). + +> Here’s an [example] +(https://github.com/webpack/analyse/blob/master/app/pages/upload/example.json) +of this function’s output. + + +### `stats.toString(options)` + +Returns a formatted string of the compilation information (similar to +[CLI](/api/cli) output). + +Options are the same as [`stats.toJson(options)`](/api/node#stats-tojson-options-) with one addition: + +``` js +stats.toString({ + // Add console colors + colors: true +}); +``` + +Here’s an example of `stats.toString()` usage: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, stats) => { + if (err) { + console.error(err); + return; + } + + console.log(stats.toString({ + chunks: false, // Makes the build much quieter + colors: true // Shows colors in the console + })); +}); +``` + + +## MultiCompiler + +The `MultiCompiler` module allows webpack to run multiple configurations in +separate compilers. If the `options` parameter in the webpack's NodeJS api is +an array of options, webpack applies separate compilers and calls the +`callback` method at the end of each compiler execution. + +``` js-with-links +var webpack = require('webpack'); + +webpack([ + { entry: './index1.js', output: { filename: 'bundle1.js' } }, + { entry: './index2.js', output: { filename: 'bundle2.js' } } +], (err, [stats](#stats-object)) => { + process.stdout.write(stats.toString() + "\n"); +}) +``` + +W> Multiple configurations will __not be run in parallel__. Each +configuration is only processed after the previous one has finished +processing. To process them in parallel, you can use a third-party solution +like [parallel-webpack](https://www.npmjs.com/package/parallel-webpack). + + +## Error Handling + +For a good error handling, you need to account for these three types of errors: + +- Fatal webpack errors (wrong configuration, etc) +- Compilation errors (missing modules, syntax errors, etc) +- Compilation warnings + +Here’s an example that does all that: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, stats) => { + if (err) { + console.error(err.stack || err); + if (err.details) { + console.error(err.details); + } + return; + } + + const info = stats.toJson(); + + if (stats.hasErrors()) { + console.error(info.errors); + } + + if (stats.hasWarnings()) { + console.warn(info.warnings); + } + + // Log result... +}); +``` + + +## Custom File Systems + +By default, webpack reads files and writes files to disk using a normal file +system. However, it is possible to change the input or output behavior using a +different kind of file system (memory, webDAV, etc). To accomplish this, one +can change the `inputFileSystem` or `outputFileSystem`. For example, you can +replace the default `outputFileSystem` with +[`memory-fs`](https://github.com/webpack/memory-fs) to write files to memory +instead of to disk: + +``` js +const MemoryFS = require('memory-fs'); +const webpack = require('webpack'); + +const fs = new MemoryFS(); +const compiler = webpack({ /* options*/ }); + +compiler.outputFileSystem = fs; +compiler.run((err, stats) => { + // Read the output later: + const content = fs.readFileSync('...'); +}); +``` + +Note that this is what +[webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware), +used by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) +and many other packages, uses to mysteriously hide your files but continue +serving them up to the browser! + +T> The output file system you provide needs to be compatible with Node’s own +[`fs`](https://nodejs.org/api/fs.html) interface, which requires the `mkdirp` +and `join` helper methods. + + +# Resolvers + +Resolvers are created using the `enhanced-resolve` package. The `Resolver` +class extends the `tapable` class and uses `tapable` to provide a few hooks. +The `enhanced-resolve` package can be used directly to create new resolvers, +however any [`compiler` instance](/api/node/#compiler-instance) has a few resolver instances that can be +tapped into. + +Before reading on, make sure you at least skim through the +[`enhanced-resolve`](https://github.com/webpack/enhanced-resolve) and [`tapable`](/api/plugins/#tapable) documentation. + + +## Types + +There are three types of built-in resolvers available on the `compiler` class: + +- Normal: Resolves a module via an absolute or relative path. +- Context: Resolves a module within a given context. +- Loader: Resolves a webpack [loader](/loaders). + +Depending on need, any one of these built-in resolver used by the `compiler` +can be customized via plugins as such: + +``` js +compiler.resolverFactory.plugin('resolver [type]', resolver => { + resolver.hooks.resolve.tapAsync('MyPlugin', params => { + // ... + }); +}); +``` + +Where `[type]` is one of the three resolvers mention above, specified as: + +- `normal` +- `context` +- `loader` + + +See the `enhanced-resolve` [documentation](https://github.com/webpack/enhanced-resolve) for a full list of hooks and +descriptions. + + +## Configuration Options + +The resolvers mentioned above can also be customized via a configuration file +with the [`resolve`](/configuration/resolve/) or [`resolveLoader`](/configuration/resolve/#resolveloader) options. These options allow +users to change the resolving behavior through a variety of options including +through resolve `plugins`. + +The resolver plugins, e.g. [`DirectoryNamedPlugin`](https://github.com/shaketbaby/directory-named-webpack-plugin), can be included +directly in `resolve.plugins` rather than using standard plugins. Note that the +`resolve` configuration affects the `normal` and `context` resolvers while +`resolveLoader` is used to modify the `loader` resolver. + + +# Stats Data + +When compiling source code with webpack, users can generate a JSON file containing statistics about modules. These statistics can be used to analyze an application's dependency graph as well as to optimize compilation speed. The file is typically generated with the following CLI command: + +``` bash +webpack --profile --json > compilation-stats.json +``` + +The `--json > compilation-stats.json` flag indicates to webpack that it should emit the `compilation-stats.json` containing the dependency graph and various other build information. Typically, the `--profile` flag is also added so that a `profile` section is added to each [`modules` object](#module-objects) containing module-specific compilation stats. + + +## Structure + +The top-level structure of the output JSON file is fairly straightforward but there are a few nested data structures as well. Each nested structure has a dedicated section below to make this document more consumable. Note that you can click links within the top-level structure below to jump to relevant sections and documentation: + +```js-with-links +{ + "version": "1.4.13", // Version of webpack used for the compilation + "hash": "11593e3b3ac85436984a", // Compilation specific hash + "time": 2469, // Compilation time in milliseconds + "filteredModules": 0, // A count of excluded modules when [`exclude`](/configuration/stats/#stats) is passed to the [`toJson`](/api/node/#stats-tojson-options-) method + "outputPath": "/", // path to webpack output directory + "assetsByChunkName": { + // Chunk name to emitted asset(s) mapping + "main": "web.js?h=11593e3b3ac85436984a", + "named-chunk": "named-chunk.web.js", + "other-chunk": [ + "other-chunk.js", + "other-chunk.css" + ] + }, + "assets": [ + // A list of [asset objects](#asset-objects) + ], + "chunks": [ + // A list of [chunk objects](#chunk-objects) + ], + "modules": [ + // A list of [module objects](#module-objects) + ], + "errors": [ + // A list of [error strings](#errors-and-warnings) + ], + "warnings": [ + // A list of [warning strings](#errors-and-warnings) + ] +} +``` + + +### Asset Objects + +Each `assets` object represents an `output` file emitted from the compilation. They all follow a similar structure: + +<!-- eslint-skip --> + +```js +{ + "chunkNames": [], // The chunks this asset contains + "chunks": [ 10, 6 ], // The chunk IDs this asset contains + "emitted": true, // Indicates whether or not the asset made it to the `output` directory + "name": "10.web.js", // The `output` filename + "size": 1058 // The size of the file in bytes +} +``` + + +### Chunk Objects + +Each `chunks` object represents a group of modules known as a [chunk](/glossary#c). Each object follows the following structure: + +```js-with-links +{ + "entry": true, // Indicates whether or not the chunk contains the webpack runtime + "files": [ + // An array of filename strings that contain this chunk + ], + "filteredModules": 0, // See the description in the [top-level structure](#structure) above + "id": 0, // The ID of this chunk + "initial": true, // Indicates whether this chunk is loaded on initial page load or [on demand](/guides/lazy-loading) + "modules": [ + // A list of [module objects](#module-objects) + "web.js?h=11593e3b3ac85436984a" + ], + "names": [ + // An list of chunk names contained within this chunk + ], + "origins": [ + // See the description below... + ], + "parents": [], // Parent chunk IDs + "rendered": true, // Indicates whether or not the chunk went through Code Generation + "size": 188057 // Chunk size in bytes +} +``` + +The `chunks` object will also contain a list of `origins` describing how the given chunk originated. Each `origins` object follows the following schema: + +```js-with-links +{ + "loc": "", // Lines of code that generated this chunk + "module": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleId": 0, // The ID of the module + "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleName": "./lib/index.web.js", // Relative path to the module + "name": "main", // The name of the chunk + "reasons": [ + // A list of the same `reasons` found in [module objects](#module-objects) + ] +} +``` + + +### Module Objects + +What good would these statistics be without some description of the compiled application's actual modules? Each module in the dependency graph is represented by the following structure: + +```js-with-links +{ + "assets": [ + // A list of [asset objects](#asset-objects) + ], + "built": true, // Indicates that the module went through [Loaders](/concepts/loaders), Parsing, and Code Generation + "cacheable": true, // Whether or not this module is cacheable + "chunks": [ + // IDs of chunks that contain this module + ], + "errors": 0, // Number of errors when resolving or processing the module + "failed": false, // Whether or not compilation failed on this module + "id": 0, // The ID of the module (analagous to [`module.id`](/api/module-variables#module-id-commonjs-)) + "identifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // A unique ID used internally + "name": "./lib/index.web.js", // Path to the actual file + "optional": false, // All requests to this module are with `try... catch` blocks (irrelevant with ESM) + "prefetched": false, // Indicates whether or not the module was [prefetched](/plugins/prefetch-plugin) + "profile": { + // Module specific compilation stats corresponding to the [`--profile` flag](/api/cli#profiling) (in milliseconds) + "building": 73, // Loading and parsing + "dependencies": 242, // Building dependencies + "factory": 11 // Resolving dependencies + }, + "reasons": [ + // See the description below... + ], + "size": 3593, // Estimated size of the module in bytes + "source": "// Should not break it...\r\nif(typeof...", // The stringified raw source + "warnings": 0 // Number of warnings when resolving or processing the module +} +``` + +Every module also contains a list of `reasons` objects describing why that module was included in the dependency graph. Each "reason" is similar to the `origins` seen above in the [chunk objects](#chunk-objects) section: + +```js-with-links +{ + "loc": "33:24-93", // Lines of code that caused the module to be included + "module": "./lib/index.web.js", // Relative path to the module based on [context](/configuration/entry-context/#context) + "moduleId": 0, // The ID of the module + "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleName": "./lib/index.web.js", // A more readable name for the module (used for "pretty-printing") + "type": "require.context", // The [type of request](/api/module-methods) used + "userRequest": "../../cases" // Raw string used for the `import` or `require` request +} +``` + + +### Errors and Warnings + +The `errors` and `warnings` properties each contain a list of strings. Each string contains a message and stack trace: + +``` bash +../cases/parsing/browserify/index.js +Critical dependencies: +2:114-121 This seem to be a pre-built javascript file. Even while this is possible, it's not recommended. Try to require to original source to get better results. + @ ../cases/parsing/browserify/index.js 2:114-121 +``` + +W> Note that the stack traces are removed when `errorDetails: false` is passed to the `toJson` method. The `errorDetails` option is set to `true` by default. + + +# Loader API + +A loader is just a JavaScript module that exports a function. The [loader runner](https://github.com/webpack/loader-runner) calls this function and passes the result of the previous loader or the resource file into it. The `this` context of the function is filled-in by webpack and the [loader runner](https://github.com/webpack/loader-runner) with some useful methods that allow the loader (among other things) to change its invocation style to async, or get query parameters. + +The first loader is passed one argument: the content of the resource file. The compiler expects a result from the last loader. The result should be a `String` or a `Buffer` (which is converted to a string), representing the JavaScript source code of the module. An optional SourceMap result (as JSON object) may also be passed. + +A single result can be returned in __sync mode__. For multiple results the `this.callback()` must be called. In __async mode__ `this.async()` must be called to indicate that the [loader runner](https://github.com/webpack/loader-runner) should wait for an asynchronous result. It returns `this.callback()`. Then the loader must return `undefined` and call that callback. + + +## Examples + +The following sections provide some basic examples of the different types of loaders. Note that the `map` and `meta` parameters are optional, see [`this.callback`](/api/loaders#this-callback) below. + +### Synchronous Loaders + +Either `return` or `this.callback` can be used to return the transformed `content` synchronously: + +__sync-loader.js__ + +``` js +module.exports = function(content, map, meta) { + return someSyncOperation(content); +}; +``` + +The `this.callback` method is more flexible as it allows multiple arguments to be passed as opposed to just the `content`. + +__sync-loader-with-multiple-results.js__ + +``` js +module.exports = function(content, map, meta) { + this.callback(null, someSyncOperation(content), map, meta); + return; // always return undefined when calling callback() +}; +``` + +### Asynchronous Loaders + +For asynchronous loaders, [`this.async`](/api/loaders#this-async) is used to retrieve the `callback` function: + +__async-loader.js__ + +``` js +module.exports = function(content, map, meta) { + var callback = this.async(); + someAsyncOperation(content, function(err, result) { + if (err) return callback(err); + callback(null, result, map, meta); + }); +}; +``` + +__async-loader-with-multiple-results.js__ + +``` js +module.exports = function(content, map, meta) { + var callback = this.async(); + someAsyncOperation(content, function(err, result, sourceMaps, meta) { + if (err) return callback(err); + callback(null, result, sourceMaps, meta); + }); +}; +``` + +T> Loaders were originally designed to work in synchronous loader pipelines, like Node.js (using [enhanced-require](https://github.com/webpack/enhanced-require)), _and_ asynchronous pipelines, like in webpack. However, since expensive synchronous computations are a bad idea in a single-threaded environment like Node.js, we advise to make your loader asynchronously if possible. Synchronous loaders are ok if the amount of computation is trivial. + + +### "Raw" Loader + +By default, the resource file is converted to a UTF-8 string and passed to the loader. By setting the `raw` flag, the loader will receive the raw `Buffer`. Every loader is allowed to deliver its result as `String` or as `Buffer`. The compiler converts them between loaders. + +__raw-loader.js__ + +``` js +module.exports = function(content) { + assert(content instanceof Buffer); + return someSyncOperation(content); + // return value can be a `Buffer` too + // This is also allowed if loader is not "raw" +}; +module.exports.raw = true; +``` + + +### Pitching Loader + +Loaders are __always__ called from right to left. There are some instances where the loader only cares about the __metadata__ behind a request and can ignore the results of the previous loader. The `pitch` method on loaders is called from __left to right__ before the loaders are actually executed (from right to left). For the following [`use`](/configuration/module#rule-use) configuration: + +``` js +module.exports = { + //... + module: { + rules: [ + { + //... + use: [ + 'a-loader', + 'b-loader', + 'c-loader' + ] + } + ] + } +}; +``` + +These steps would occur: + +``` diff +|- a-loader `pitch` + |- b-loader `pitch` + |- c-loader `pitch` + |- requested module is picked up as a dependency + |- c-loader normal execution + |- b-loader normal execution +|- a-loader normal execution +``` + +So why might a loader take advantage of the "pitching" phase? + +First, the `data` passed to the `pitch` method is exposed in the execution phase as well under `this.data` and could be useful for capturing and sharing information from earlier in the cycle. + +``` js +module.exports = function(content) { + return someSyncOperation(content, this.data.value); +}; + +module.exports.pitch = function(remainingRequest, precedingRequest, data) { + data.value = 42; +}; +``` + +Second, if a loader delivers a result in the `pitch` method the process turns around and skips the remaining loaders. In our example above, if the `b-loader`s `pitch` method returned something: + +``` js +module.exports = function(content) { + return someSyncOperation(content); +}; + +module.exports.pitch = function(remainingRequest, precedingRequest, data) { + if (someCondition()) { + return 'module.exports = require(' + JSON.stringify('-!' + remainingRequest) + ');'; + } +}; +``` + +The steps above would be shortened to: + +``` diff +|- a-loader `pitch` + |- b-loader `pitch` returns a module +|- a-loader normal execution +``` + +See the [bundle-loader](https://github.com/webpack-contrib/bundle-loader) for a good example of how this process can be used in a more meaningful way. + + +## The Loader Context + +The loader context represents the properties that are available inside of a loader assigned to the `this` property. + +Given the following example this require call is used: +In `/abc/file.js`: + +``` js +require('./loader1?xyz!loader2!./resource?rrr'); +``` + + +### `this.version` + +__Loader API version.__ Currently `2`. This is useful for providing backwards compatibility. Using the version you can specify custom logic or fallbacks for breaking changes. + + +### `this.context` + +__The directory of the module.__ Can be used as context for resolving other stuff. + +In the example: `/abc` because `resource.js` is in this directory + + +### `this.rootContext` + +Starting with webpack 4, the formerly `this.options.context` is provided as `this.rootContext`. + + +### `this.request` + +The resolved request string. + +In the example: `"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"` + + +### `this.query` + +1. If the loader was configured with an [`options`](/configuration/module/#useentry) object, this will point to that object. +2. If the loader has no `options`, but was invoked with a query string, this will be a string starting with `?`. + +T> Use the [`getOptions` method](https://github.com/webpack/loader-utils#getoptions) from `loader-utils` to extract given loader options. + + +### `this.callback` + +A function that can be called synchronously or asynchronously in order to return multiple results. The expected arguments are: + +<!-- eslint-skip --> + +```js +this.callback( + err: Error | null, + content: string | Buffer, + sourceMap?: SourceMap, + meta?: any +); +``` + +1. The first argument must be an `Error` or `null` +2. The second argument a `string` or a [`Buffer`](https://nodejs.org/api/buffer.html). +3. Optional: The third argument must be a source map that is parsable by [this module](https://github.com/mozilla/source-map). +4. Optional: The fourth option, ignored by webpack, can be anything (e.g. some meta data). + +T> It can be useful to pass an abstract syntax tree (AST), like [`ESTree`](https://github.com/estree/estree), as the fourth argument (`meta`) to speed up the build time if you want to share common ASTs between loaders. + +In case this function is called, you should return undefined to avoid ambiguous loader results. + + +### `this.async` + +Tells the [loader-runner](https://github.com/webpack/loader-runner) that the loader intends to call back asynchronously. Returns `this.callback`. + + +### `this.data` + +A data object shared between the pitch and the normal phase. + + +### `this.cacheable` + +A function that sets the cacheable flag: + +``` typescript +cacheable(flag = true: boolean) +``` + +By default, loader results are flagged as cacheable. Call this method passing `false` to make the loader's result not cacheable. + +A cacheable loader must have a deterministic result, when inputs and dependencies haven't changed. This means the loader shouldn't have other dependencies than specified with `this.addDependency`. + + +### `this.loaders` + +An array of all the loaders. It is writeable in the pitch phase. + +<!-- eslint-skip --> + +```js +loaders = [{request: string, path: string, query: string, module: function}] +``` + +In the example: + +``` js +[ + { + request: '/abc/loader1.js?xyz', + path: '/abc/loader1.js', + query: '?xyz', + module: [Function] + }, + { + request: '/abc/node_modules/loader2/index.js', + path: '/abc/node_modules/loader2/index.js', + query: '', + module: [Function] + } +]; +``` + + +### `this.loaderIndex` + +The index in the loaders array of the current loader. + +In the example: in loader1: `0`, in loader2: `1` + + +### `this.resource` + +The resource part of the request, including query. + +In the example: `"/abc/resource.js?rrr"` + + +### `this.resourcePath` + +The resource file. + +In the example: `"/abc/resource.js"` + + +### `this.resourceQuery` + +The query of the resource. + +In the example: `"?rrr"` + + +### `this.target` + +Target of compilation. Passed from configuration options. + +Example values: `"web"`, `"node"` + + +### `this.webpack` + +This boolean is set to true when this is compiled by webpack. + +T> Loaders were originally designed to also work as Babel transforms. Therefore if you write a loader that works for both, you can use this property to know if there is access to additional loaderContext and webpack features. + + +### `this.sourceMap` + +Should a source map be generated. Since generating source maps can be an expensive task, you should check if source maps are actually requested. + + +### `this.emitWarning` + +``` typescript +emitWarning(warning: Error) +``` + +Emit a warning. + + +### `this.emitError` + +``` typescript +emitError(error: Error) +``` + +Emit an error. + + +### `this.loadModule` + +``` typescript +loadModule(request: string, callback: function(err, source, sourceMap, module)) +``` + +Resolves the given request to a module, applies all configured loaders and calls back with the generated source, the sourceMap and the module instance (usually an instance of [`NormalModule`](https://github.com/webpack/webpack/blob/master/lib/NormalModule.js)). Use this function if you need to know the source code of another module to generate the result. + + +### `this.resolve` + +``` typescript +resolve(context: string, request: string, callback: function(err, result: string)) +``` + +Resolve a request like a require expression. + + +### `this.addDependency` + +``` typescript +addDependency(file: string) +dependency(file: string) // shortcut +``` + +Adds a file as dependency of the loader result in order to make them watchable. For example, [`html-loader`](https://github.com/webpack-contrib/html-loader) uses this technique as it finds `src` and `src-set` attributes. Then, it sets the url's for those attributes as dependencies of the html file that is parsed. + + +### `this.addContextDependency` + +``` typescript +addContextDependency(directory: string) +``` + +Add a directory as dependency of the loader result. + + +### `this.clearDependencies` + +``` typescript +clearDependencies() +``` + +Remove all dependencies of the loader result. Even initial dependencies and these of other loaders. Consider using `pitch`. + + +### `this.emitFile` + +``` typescript +emitFile(name: string, content: Buffer|string, sourceMap: {...}) +``` + +Emit a file. This is webpack-specific. + + +### `this.fs` + +Access to the `compilation`'s `inputFileSystem` property. + + +## Deprecated context properties + +W> The usage of these properties is highly discouraged since we are planning to remove them from the context. They are still listed here for documentation purposes. + + +### `this.exec` + +``` typescript +exec(code: string, filename: string) +``` + +Execute some code fragment like a module. See [this comment](https://github.com/webpack/webpack.js.org/issues/1268#issuecomment-313513988) for a replacement method if needed. + + +### `this.resolveSync` + +``` typescript +resolveSync(context: string, request: string) -> string +``` + +Resolve a request like a require expression. + + +### `this.value` + +Pass values to the next loader. If you know what your result exports if executed as module, set this value here (as a only element array). + + +### `this.inputValue` + +Passed from the last loader. If you would execute the input argument as module, consider reading this variable for a shortcut (for performance). + + +### `this.options` + +W> The `options` property has been deprecated in webpack 3 and removed in webpack 4. + + +### `this.debug` + +A boolean flag. It is set when in debug mode. + + +### `this.minimize` + +Should the result be minimized. + + +### `this._compilation` + +Hacky access to the Compilation object of webpack. + + +### `this._compiler` + +Hacky access to the Compiler object of webpack. + + +### `this._module` + +Hacky access to the Module object being loaded. + + +# Module Variables + +This section covers all __variables__ available in code compiled with webpack. Modules will have access to certain data from the compilation process through `module` and other variables. + + +### `module.loaded` (NodeJS) + +This is `false` if the module is currently executing, and `true` if the sync execution has finished. + + +### `module.hot` (webpack-specific) + +Indicates whether or not [Hot Module Replacement](/concepts/hot-module-replacement) is enabled and provides an interface to the process. See the [HMR API page](/api/hot-module-replacement) for details. + + +### `module.id` (CommonJS) + +The ID of the current module. + +``` javascript +module.id === require.resolve('./file.js'); +``` + + +### `module.exports` (CommonJS) + +Defines the value that will be returned when a consumer makes a `require` call to the module (defaults to a new object). + +``` javascript +module.exports = function doSomething() { + // Do something... +}; +``` + +W> This CANNOT be used in an asynchronous function. + + +### `exports` (CommonJS) + +This variable is equal to default value of `module.exports` (i.e. an object). If `module.exports` gets overwritten, `exports` will no longer be exported. + +``` javascript +exports.someValue = 42; +exports.anObject = { + x: 123 +}; +exports.aFunction = function doSomething() { + // Do something +}; +``` + + +### `global` (NodeJS) + +See [node.js global](https://nodejs.org/api/globals.html#globals_global). + + +### `process` (NodeJS) + +See [node.js process](https://nodejs.org/api/process.html). + + +### `__dirname` (NodeJS) + +Depending on the config option `node.__dirname`: + +- `false`: Not defined +- `mock`: equal "/" +- `true`: [node.js __dirname](https://nodejs.org/api/globals.html#globals_dirname) + +If used inside a expression that is parsed by the Parser, the config option is treated as `true`. + + +### `__filename` (NodeJS) + +Depending on the config option `node.__filename`: + +- `false`: Not defined +- `mock`: equal "/index.js" +- `true`: [node.js __filename](https://nodejs.org/api/globals.html#globals_filename) + +If used inside a expression that is parsed by the Parser, the config option is treated as `true`. + + +### `__resourceQuery` (webpack-specific) + +The resource query of the current module. If the following `require` call were made, then the query string would be available in `file.js`. + +``` javascript +require('file.js?test'); +``` + +__file.js__ + +``` javascript +__resourceQuery === '?test'; +``` + + +### `__webpack_public_path__` (webpack-specific) + +Equals the config options `output.publicPath`. + + +### `__webpack_require__` (webpack-specific) + +The raw require function. This expression isn't parsed by the Parser for dependencies. + + +### `__webpack_chunk_load__` (webpack-specific) + +The internal chunk loading function. Takes two arguments: + +- `chunkId` The id for the chunk to load. +- `callback(require)` A callback function called once the chunk is loaded. + + +### `__webpack_modules__` (webpack-specific) + +Access to the internal object of all modules. + + +### `__webpack_hash__` (webpack-specific) + +This variable is only available with the `HotModuleReplacementPlugin` or the `ExtendedAPIPlugin`. It provides access to the hash of the compilation. + + +### `__non_webpack_require__` (webpack-specific) + +Generates a `require` function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available. + + +### `DEBUG` (webpack-specific) + +Equals the config option `debug`. + + +# Parser + +The `parser` instance, found in the `compiler`, is used to parse each module +being processed by webpack. The `parser` is yet another webpack class that +extends `tapable` and provides a variety of `tapable` hooks that can be used by +plugin authors to customize the parsing process. + +The `parser` is found within [module factories](/api/compiler-hooks/#normalmodulefactory) and therefore takes little +more work to access: + +``` js +compiler.hooks.normalModuleFactory.tap('MyPlugin', factory => { + factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => { + parser.hooks.someHook.tap(/* ... */); + }); +}); +``` + +As with the `compiler`, `tapAsync` and `tapPromise` may also be available +depending on the type of hook. + + +## Hooks + +The following lifecycle hooks are exposed by the `parser` and can be accessed +as such: + + +### evaluateTypeof + +`SyncBailHook` + +Evaluate the type of an identifier. + +Parameters: `expression` + + +### evaluate + +`SyncBailHook` + +Evaluate an expression. + +Parameters: `expression` + + +### evaluateIdentifier + +`SyncBailHook` + +Evaluate an identifier that is a free variable. + +Parameters: `expression` + + +### evaluateDefinedIdentifier + +`SyncBailHook` + +Evaluate an identifier that is a defined variable. + +Parameters: `expression` + + +### evaluateCallExpressionMember + +`SyncBailHook` + +Evaluate a call to a member function of a successfully evaluated expression. + +Parameters: `expression` `param` + + +### statement + +`SyncBailHook` + +General purpose hook that is called when parsing statements in a code fragment. + +Parameters: `statement` + + +### statementIf + +`SyncBailHook` + +... + +Parameters: `statement` + + +### label + +`SyncBailHook` + +... + +Parameters: `statement` + + +### import + +`SyncBailHook` + +... + +Parameters: `statement` `source` + + +### importSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `source` `exportName` `identifierName` + + +### export + +`SyncBailHook` + +... + +Parameters: `statement` + + +### exportImport + +`SyncBailHook` + +... + +Parameters: `statement` `source` + + +### exportDeclaration + +`SyncBailHook` + +... + +Parameters: `statement` `declaration` + + +### exportExpression + +`SyncBailHook` + +... + +Parameters: `statement` `declaration` + + +### exportSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `identifierName` `exportName` `index` + + +### exportImportSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `source` `identifierName` `exportName` `index` + + +### varDeclaration + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationLet + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationConst + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationVar + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### canRename + +`SyncBailHook` + +... + +Parameters: `initExpression` + + +### rename + +`SyncBailHook` + +... + +Parameters: `initExpression` + + +### assigned + +`SyncBailHook` + +... + +Parameters: `expression` + + +### assign + +`SyncBailHook` + +... + +Parameters: `expression` + + +### typeof + +`SyncBailHook` + +... + +Parameters: `expression` + + +### call + +`SyncBailHook` + +... + +Parameters: `expression` + + +### callAnyMember + +`SyncBailHook` + +... + +Parameters: `expression` + + +### new + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expression + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expressionAnyMember + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expressionConditionalOperator + +`SyncBailHook` + +... + +Parameters: `expression` + + +### program + +`SyncBailHook` + +Get access to the abstract syntax tree (AST) of a code fragment + +Parameters: `ast` `comments` diff --git a/src/content/concepts/_concepts_all.md b/src/content/concepts/_concepts_all.md new file mode 100644 index 000000000000..7ea61cfe8aaa --- /dev/null +++ b/src/content/concepts/_concepts_all.md @@ -0,0 +1,1086 @@ + + +# Concepts + +At its core, __webpack__ is a _static module bundler_ for modern JavaScript applications. When webpack processes your application, it internally builds a [dependency graph](/concepts/dependency-graph/) which maps every module your project needs and generates one or more _bundles_. + +T> Learn more about JavaScript modules and webpack modules [here](/concepts/modules). + +Since version 4.0.0, __webpack does not require a configuration file__ to bundle your project, nevertheless it is [incredibly configurable](/configuration) to better fit your needs. + +To get started you only need to understand its __Core Concepts__: + +- [Entry](#entry) +- [Output](#output) +- [Loaders](#loaders) +- [Plugins](#plugins) +- [Mode](#mode) +- [Browser Compatibility](#browser-compatibility) + +This document is intended to give a __high-level__ overview of these concepts, while providing links to detailed concept specific use cases. + +For a better understanding of the ideas behind module bundlers and how they work under the hood consult these resources: + +- [Manually Bundling an Application](https://www.youtube.com/watch?v=UNMkLHzofQI) +- [Live Coding a Simple Module Bundler](https://www.youtube.com/watch?v=Gc9-7PBqOC8) +- [Detailed Explanation of a Simple Module Bundler](https://github.com/ronami/minipack) + + +## Entry + +An __entry point__ indicates which module webpack should use to begin building out its internal [dependency graph](/concepts/dependency-graph/). webpack will figure out which other modules and libraries that entry point depends on (directly and indirectly). + +By default its value is `./src/index.js`, but you can specify a different (or multiple entry points) by configuring the __entry__ property in the [webpack configuration](/configuration). For example: + +__webpack.config.js__ + +``` js +module.exports = { + entry: './path/to/my/entry/file.js' +}; +``` + +T> Learn more in the [entry points](/concepts/entry-points) section. + + +## Output + +The __output__ property tells webpack where to emit the _bundles_ it creates and how to name these files. It defaults to `./dist/main.js` for the main output file and to the `./dist` folder for any other generated file. + +You can configure this part of the process by specifying an `output` field in your configuration: + +__webpack.config.js__ + +```javascript +const path = require('path'); + +module.exports = { + entry: './path/to/my/entry/file.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'my-first-webpack.bundle.js' + } +}; +``` + +In the example above, we use the `output.filename` and the `output.path` properties to tell webpack the name of our bundle and where we want it to be emitted to. In case you're wondering about the path module being imported at the top, it is a core [Node.js module](https://nodejs.org/api/modules.html) that gets used to manipulate file paths. + +T> The `output` property has [many more configurable features](/configuration/output) and if you like to know more about the concepts behind it, you can [read more in the output section](/concepts/output). + + +## Loaders + +Out of the box, webpack only understands JavaScript and JSON files. __Loaders__ allow webpack to process other types of files and convert them into valid [modules](/concepts/modules) that can be consumed by your application and added to the dependency graph. + +W> Note that the ability to `import` any type of module, e.g. `.css` files, is a feature specific to webpack and may not be supported by other bundlers or task runners. We feel this extension of the language is warranted as it allows developers to build a more accurate dependency graph. + +At a high level, __loaders__ have two properties in your webpack configuration: + +1. The `test` property identifies which file or files should be transformed. +2. The `use` property indicates which loader should be used to do the transforming. + +__webpack.config.js__ + +```javascript +const path = require('path'); + +module.exports = { + output: { + filename: 'my-first-webpack.bundle.js' + }, + module: { + rules: [ + { test: /\.txt$/, use: 'raw-loader' } + ] + } +}; +``` + +The configuration above has defined a `rules` property for a single module with two required properties: `test` and `use`. This tells webpack's compiler the following: + +> "Hey webpack compiler, when you come across a path that resolves to a '.txt' file inside of a `require()`/`import` statement, __use__ the `raw-loader` to transform it before you add it to the bundle." + +W> It is important to remember that when defining rules in your webpack config, you are defining them under `module.rules` and not `rules`. For your benefit, webpack will warn you if this is done incorrectly. + +You can check further customization when including loaders in the [loaders section](/concepts/loaders). + + +## Plugins + +While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables. + +T> Check out the [plugin interface](/api/plugins) and how to use it to extend webpacks capabilities. + +In order to use a plugin, you need to `require()` it and add it to the `plugins` array. Most plugins are customizable through options. Since you can use a plugin multiple times in a config for different purposes, you need to create an instance of it by calling it with the `new` operator. + +__webpack.config.js__ + +```javascript +const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm +const webpack = require('webpack'); //to access built-in plugins + +module.exports = { + module: { + rules: [ + { test: /\.txt$/, use: 'raw-loader' } + ] + }, + plugins: [ + new HtmlWebpackPlugin({template: './src/index.html'}) + ] +}; +``` + +In the example above, the `html-webpack-plugin` generates an HTML file for your application by injecting automatically all your generated bundles. + +T> There are many plugins that webpack provides out of the box! Check out the [list of plugins](/plugins). + +Using plugins in your webpack config is straightforward - however, there are many use cases that are worth further exploration. [Learn more about them here](/concepts/plugins). + + +## Mode + +By setting the `mode` parameter to either `development`, `production` or `none`, you can enable webpack's built-in optimizations that correspond to each environment. The default value is `production`. + +```javascript +module.exports = { + mode: 'production' +}; +``` + +Learn more about the [mode configuration here](/concepts/mode) and what optimizations take place on each value. + + +## Browser Compatibility + +webpack supports all browsers that are [ES5-compliant](https://kangax.github.io/compat-table/es5/) (IE8 and below are not supported). webpack needs `Promise` for `import()` and `require.ensure()`. If you want to support older browsers, you will need to [load a polyfill](/guides/shimming/) before using these expressions. + + +# Entry Points + +As mentioned in [Getting Started](/guides/getting-started/#using-a-configuration), there are multiple ways to define the `entry` property in your webpack configuration. We will show you the ways you __can__ configure the `entry` property, in addition to explaining why it may be useful to you. + + +## Single Entry (Shorthand) Syntax + +Usage: `entry: string|Array<string>` + +__webpack.config.js__ + +```javascript +module.exports = { + entry: './path/to/my/entry/file.js' +}; +``` + +The single entry syntax for the `entry` property is a shorthand for: + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + main: './path/to/my/entry/file.js' + } +}; +``` + +T> __What happens when you pass an array to `entry`?__ Passing an array of file paths to the `entry` property creates what is known as a __"multi-main entry"__. This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk". + +This is a great choice when you are looking to quickly setup a webpack configuration for an application or tool with one entry point (i.e., a library). However, there is not much flexibility in extending or scaling your configuration with this syntax. + + +## Object Syntax + +Usage: `entry: {[entryChunkName: string]: string|Array<string>}` + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + app: './src/app.js', + adminApp: './src/adminApp.js' + } +}; +``` + +The object syntax is more verbose. However, this is the most scalable way of defining entry/entries in your application. + +T> __"Scalable webpack configurations"__ are ones that can be reused and combined with other partial configurations. This is a popular technique used to separate concerns by environment, build target and runtime. They are then merged using specialized tools like [webpack-merge](https://github.com/survivejs/webpack-merge). + + +## Scenarios + +Below is a list of entry configurations and their real-world use cases: + +### Separate App and Vendor Entries + +T> In webpack version < 4 it was common to add vendors as separate entrypoint to compile it as separate file (in combination with the `CommonsChunkPlugin`). This is discouraged in webpack 4. Instead the `optimization.splitChunks` option takes care of separating vendors and app modules and creating a separate file. __Do not__ create a entry for vendors or other stuff which is not the starting point of execution. + +### Multi Page Application + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + pageOne: './src/pageOne/index.js', + pageTwo: './src/pageTwo/index.js', + pageThree: './src/pageThree/index.js' + } +}; +``` + +__What does this do?__ We are telling webpack that we would like 3 separate dependency graphs (like the above example). + +__Why?__ In a multi-page application, the server is going to fetch a new HTML document for you. The page reloads this new document and assets are redownloaded. However, this gives us the unique opportunity to do multiple things: + +- Use `optimization.splitChunks` to create bundles of shared application code between each page. Multi-page applications that reuse a lot of code/modules between entry points can greatly benefit from these techniques, as the amount of entry points increase. + +T> As a rule of thumb: for each HTML document use exactly one entry point. + + +# Output + +Configuring the `output` configuration options tells webpack how to write the compiled files to disk. Note that, while there can be multiple `entry` points, only one `output` configuration is specified. + + +## Usage + +The minimum requirements for the `output` property in your webpack config is to set its value to an object including the following thing: + +- A `filename` to use for the output file(s). + +__webpack.config.js__ + +```javascript +module.exports = { + output: { + filename: 'bundle.js', + } +}; +``` + +This configuration would output a single `bundle.js` file into the `dist` directory. + + +## Multiple Entry Points + +If your configuration creates more than a single "chunk" (as with multiple entry points or when using plugins like CommonsChunkPlugin), you should use [substitutions](/configuration/output#output-filename) to ensure that each file has a unique name. + +```javascript +module.exports = { + entry: { + app: './src/app.js', + search: './src/search.js' + }, + output: { + filename: '[name].js', + path: __dirname + '/dist' + } +}; + +// writes to disk: ./dist/app.js, ./dist/search.js +``` + + +## Advanced + +Here's a more complicated example of using a CDN and hashes for assets: + +__config.js__ + +```javascript +module.exports = { + //... + output: { + path: '/home/proj/cdn/assets/[hash]', + publicPath: 'http://cdn.example.com/assets/[hash]/' + } +}; +``` + +In cases where the eventual `publicPath` of output files isn't known at compile time, it can be left blank and set dynamically at runtime via the `__webpack_public_path__` variable in the entry point file: + +```javascript +__webpack_public_path__ = myRuntimePublicPath; + +// rest of your application entry +``` + + +# Loaders + +Loaders are transformations that are applied on the source code of a module. They allow you to pre-process files as you `import` or “load” them. Thus, loaders are kind of like “tasks” in other build tools and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript or inline images as data URLs. Loaders even allow you to do things like `import` CSS files directly from your JavaScript modules! + + +## Example + +For example, you can use loaders to tell webpack to load a CSS file or to convert TypeScript to JavaScript. To do this, you would start by installing the loaders you need: + +``` bash +npm install --save-dev css-loader +npm install --save-dev ts-loader +``` + +And then instruct webpack to use the [`css-loader`](/loaders/css-loader) for every `.css` file and the [`ts-loader`](https://github.com/TypeStrong/ts-loader) for all `.ts` files: + +__webpack.config.js__ + +``` js +module.exports = { + module: { + rules: [ + { test: /\.css$/, use: 'css-loader' }, + { test: /\.ts$/, use: 'ts-loader' } + ] + } +}; +``` + + +## Using Loaders + +There are three ways to use loaders in your application: + +- [Configuration](#configuration) (recommended): Specify them in your __webpack.config.js__ file. +- [Inline](#inline): Specify them explicitly in each `import` statement. +- [CLI](#cli): Specify them within a shell command. + + +### Configuration + +[`module.rules`](/configuration/module/#module-rules) allows you to specify several loaders within your webpack configuration. +This is a concise way to display loaders, and helps to maintain clean code. It also offers you a full overview of each respective loader. + +Loaders are evaluated/executed from right to left. In the example below execution starts with sass-loader, continues with css-loader and finally ends with style-loader. See ["Loader Features"](/concepts/loaders/#loader-features) for more information about loaders order. + +```js-with-links-with-details +module.exports = { + module: { + rules: [ + { + test: /\.css$/, + use: [ + { loader: ['style-loader'](/loaders/style-loader) }, + { + loader: ['css-loader'](/loaders/css-loader), + options: { + modules: true + } + }, + { loader: ['sass-loader'](/loaders/sass-loader) } + ] + } + ] + } +}; +``` + + +### Inline + +It's possible to specify loaders in an `import` statement, or any [equivalent "importing" method](/api/module-methods). Separate loaders from the resource with `!`. Each part is resolved relative to the current directory. + +```js +import Styles from 'style-loader!css-loader?modules!./styles.css'; +``` + +It's possible to override any loaders in the configuration by prefixing the entire rule with `!`. + +Options can be passed with a query parameter, e.g. `?key=value&foo=bar`, or a JSON object, e.g. `?{"key":"value","foo":"bar"}`. + +T> Use `module.rules` whenever possible, as this will reduce boilerplate in your source code and allow you to debug or locate a loader faster if something goes south. + + +### CLI + +You can also use loaders through the CLI: + +```sh +webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader' +``` + +This uses the `jade-loader` for `.jade` files, and the [`style-loader`](/loaders/style-loader) and [`css-loader`](/loaders/css-loader) for `.css` files. + + +## Loader Features + +- Loaders can be chained. Each loader in the chain applies transformations to the processed resource. A chain is executed in reverse order. The first loader passes its result (resource with applied transformations) to the next one, and so forth. Finally, webpack expects JavaScript to be returned by the last loader in the chain. +- Loaders can be synchronous or asynchronous. +- Loaders run in Node.js and can do everything that’s possible there. +- Loaders can be configured with an `options` object (using `query` parameters to set options is still supported but has been deprecated). +- Normal modules can export a loader in addition to the normal `main` via `package.json` with the `loader` field. +- Plugins can give loaders more features. +- Loaders can emit additional arbitrary files. + +Loaders allow more power in the JavaScript ecosystem through preprocessing +functions (loaders). Users now have more flexibility to include fine-grained logic such as compression, packaging, language translations and [more](/loaders). + + +## Resolving Loaders + +Loaders follow the standard [module resolution](/concepts/module-resolution/). In most cases it will be loaded from the [module path](/concepts/module-resolution/#module-paths) (think `npm install`, `node_modules`). + +A loader module is expected to export a function and be written in Node.js compatible JavaScript. They are most commonly managed with npm, but you can also have custom loaders as files within your application. By convention, loaders are usually named `xxx-loader` (e.g. `json-loader`). See ["How to Write a Loader?"](/development/how-to-write-a-loader) for more information. + + +# Mode + +Providing the `mode` configuration option tells webpack to use its built-in optimizations accordingly. + +`string` + +T> Possible values for `mode` are: `none`, `development` or `production`(default). + +## Usage + +Just provide the `mode` option in the config: + +```javascript +module.exports = { + mode: 'production' +}; +``` + + +or pass it as a [CLI](/api/cli/) argument: + +```bash +webpack --mode=production +``` + +The following string values are supported: + +Option | Description +--------------------- | ----------------------- +`development` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `development`. Enables `NamedChunksPlugin` and `NamedModulesPlugin`. +`production` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `production`. Enables `FlagDependencyUsagePlugin`, `FlagIncludedChunksPlugin`, `ModuleConcatenationPlugin`, `NoEmitOnErrorsPlugin`, `OccurrenceOrderPlugin`, `SideEffectsFlagPlugin` and `TerserPlugin`. +`none` | Opts out of any default optimization options + +If not set, webpack sets `production` as the default value for `mode`. The supported values for mode are: + +T> Please remember that setting `NODE_ENV` doesn't automatically set `mode`. + + +### Mode: development + + +```diff +// webpack.development.config.js +module.exports = { ++ mode: 'development' +- devtool: 'eval', +- cache: true, +- performance: { +- hints: false +- }, +- output: { +- pathinfo: true +- }, +- optimization: { +- namedModules: true, +- namedChunks: true, +- nodeEnv: 'development', +- flagIncludedChunks: false, +- occurrenceOrder: false, +- sideEffects: false, +- usedExports: false, +- concatenateModules: false, +- splitChunks: { +- hidePathInfo: false, +- minSize: 10000, +- maxAsyncRequests: Infinity, +- maxInitialRequests: Infinity, +- }, +- noEmitOnErrors: false, +- checkWasmTypes: false, +- minimize: false, +- }, +- plugins: [ +- new webpack.NamedModulesPlugin(), +- new webpack.NamedChunksPlugin(), +- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), +- ] +} +``` + + +### Mode: production + + +```diff +// webpack.production.config.js +module.exports = { ++ mode: 'production', +- performance: { +- hints: 'warning' +- }, +- output: { +- pathinfo: false +- }, +- optimization: { +- namedModules: false, +- namedChunks: false, +- nodeEnv: 'production', +- flagIncludedChunks: true, +- occurrenceOrder: true, +- sideEffects: true, +- usedExports: true, +- concatenateModules: true, +- splitChunks: { +- hidePathInfo: true, +- minSize: 30000, +- maxAsyncRequests: 5, +- maxInitialRequests: 3, +- }, +- noEmitOnErrors: true, +- checkWasmTypes: true, +- minimize: true, +- }, +- plugins: [ +- new TerserPlugin(/* ... */), +- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), +- new webpack.optimize.ModuleConcatenationPlugin(), +- new webpack.NoEmitOnErrorsPlugin() +- ] +} +``` + + +### Mode: none + + +```diff +// webpack.custom.config.js +module.exports = { ++ mode: 'none', +- performance: { +- hints: false +- }, +- optimization: { +- flagIncludedChunks: false, +- occurrenceOrder: false, +- sideEffects: false, +- usedExports: false, +- concatenateModules: false, +- splitChunks: { +- hidePathInfo: false, +- minSize: 10000, +- maxAsyncRequests: Infinity, +- maxInitialRequests: Infinity, +- }, +- noEmitOnErrors: false, +- checkWasmTypes: false, +- minimize: false, +- }, +- plugins: [] +} +``` + +If you want to change the behavior according to the __mode__ variable inside the _webpack.config.js_, you have to export a function instead of an object: + +```javascript +var config = { + entry: './app.js' + //... +}; + +module.exports = (env, argv) => { + + if (argv.mode === 'development') { + config.devtool = 'source-map'; + } + + if (argv.mode === 'production') { + //... + } + + return config; +}; +``` + + +# Plugins + +__Plugins__ are the [backbone](https://github.com/webpack/tapable) of webpack. webpack itself is built on the __same plugin system__ that you use in your webpack configuration! + +They also serve the purpose of doing __anything else__ that a [loader](/concepts/loaders) cannot do. + + +## Anatomy + +A webpack __plugin__ is a JavaScript object that has an [`apply`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) method. This `apply` method is called by the webpack compiler, giving access to the __entire__ compilation lifecycle. + +__ConsoleLogOnBuildWebpackPlugin.js__ + +```javascript +const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; + +class ConsoleLogOnBuildWebpackPlugin { + apply(compiler) { + compiler.hooks.run.tap(pluginName, compilation => { + console.log('The webpack build process is starting!!!'); + }); + } +} +``` + +The first parameter of the tap method of the compiler hook should be a camelized version of the plugin name. It is advisable to use a constant for this so it can be reused in all hooks. + +## Usage + +Since __plugins__ can take arguments/options, you must pass a `new` instance to the `plugins` property in your webpack configuration. + +Depending on how you are using webpack, there are multiple ways to use plugins. + + +### Configuration + +__webpack.config.js__ + +```javascript +const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm +const webpack = require('webpack'); //to access built-in plugins +const path = require('path'); + +module.exports = { + entry: './path/to/my/entry/file.js', + output: { + filename: 'my-first-webpack.bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.(js|jsx)$/, + use: 'babel-loader' + } + ] + }, + plugins: [ + new webpack.ProgressPlugin(), + new HtmlWebpackPlugin({template: './src/index.html'}) + ] +}; +``` + + +### Node API + +When using the Node API, you can also pass plugins via the `plugins` property in the configuration. + +__some-node-script.js__ + +```javascript +const webpack = require('webpack'); //to access webpack runtime +const configuration = require('./webpack.config.js'); + +let compiler = webpack(configuration); + +new webpack.ProgressPlugin().apply(compiler); + +compiler.run(function(err, stats) { + // ... +}); +``` + +T> Did you know: The example seen above is extremely similar to the [webpack runtime itself!](https://github.com/webpack/webpack/blob/e7087ffeda7fa37dfe2ca70b5593c6e899629a2c/bin/webpack.js#L290-L292) There are lots of great usage examples hiding in the [webpack source code](https://github.com/webpack/webpack) that you can apply to your own configurations and scripts! + + +# Configuration + +You may have noticed that few webpack configurations look exactly alike. This is because __webpack's configuration file is a JavaScript file that exports a webpack [configuration](/configuration/).__ This configuration is then processed by webpack based upon its defined properties. + +Because it's a standard Node.js CommonJS module, you __can do the following__: + +- import other files via `require(...)` +- use utilities on npm via `require(...)` +- use JavaScript control flow expressions i. e. the `?:` operator +- use constants or variables for often used values +- write and execute functions to generate a part of the configuration + +Use these features when appropriate. + +While they are technically feasible, __the following practices should be avoided__: + +- Access CLI arguments, when using the webpack CLI (instead write your own CLI, or [use `--env`](/configuration/configuration-types/)) +- Export non-deterministic values (calling webpack twice should result in the same output files) +- Write long configurations (instead split the configuration into multiple files) + +T> The most important part to take away from this document is that there are many different ways to format and style your webpack configuration. The key is to stick with something consistent that you and your team can understand and maintain. + +The examples below describe how webpack's configuration can be both expressive and configurable because _it is code_: + +## Simple Configuration + +__webpack.config.js__ + +```javascript +var path = require('path'); + +module.exports = { + mode: 'development', + entry: './foo.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'foo.bundle.js' + } +}; +``` + +_See_: [Configuration section](/configuration/) for the all supported configuration options + +## Multiple Targets + +Along with exporting a single configuration as an object, [function](/configuration/configuration-types/#exporting-a-function) or [Promise](/configuration/configuration-types/#exporting-a-promise), you can export multiple configurations. + +_See_: [Exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) + +## Using other Configuration Languages + +webpack accepts configuration files written in multiple programming and data languages. + +_See_: [Configuration Languages](/configuration/configuration-languages/) + + +# Modules + +In [modular programming](https://en.wikipedia.org/wiki/Modular_programming), developers break programs up into discrete chunks of functionality called a _module_. + +Each module has a smaller surface area than a full program, making verification, debugging, and testing trivial. +Well-written _modules_ provide solid abstractions and encapsulation boundaries, so that each module has a coherent design and a clear purpose within the overall application. + +Node.js has supported modular programming almost since its inception. +On the web, however, support for _modules_ has been slow to arrive. +Multiple tools exist that support modular JavaScript on the web, with a variety of benefits and limitations. +webpack builds on lessons learned from these systems and applies the concept of _modules_ to any file in your project. + +## What is a webpack Module + +In contrast to [Node.js modules](https://nodejs.org/api/modules.html), webpack _modules_ can express their _dependencies_ in a variety of ways. A few examples are: + +- An [ES2015 `import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) statement +- A [CommonJS](http://www.commonjs.org/specs/modules/1.0/) `require()` statement +- An [AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md) `define` and `require` statement +- An [`@import` statement](https://developer.mozilla.org/en-US/docs/Web/CSS/@import) inside of a css/sass/less file. +- An image url in a stylesheet (`url(...)`) or html (`<img src=...>`) file. + +T> webpack 1 requires a specific loader to convert ES2015 `import`, however this is possible out of the box via webpack 2 + +## Supported Module Types + +webpack supports modules written in a variety of languages and preprocessors, via _loaders_. _Loaders_ describe to webpack __how__ to process non-JavaScript _modules_ and include these _dependencies_ into your _bundles_. +The webpack community has built _loaders_ for a wide variety of popular languages and language processors, including: + +- [CoffeeScript](http://coffeescript.org) +- [TypeScript](https://www.typescriptlang.org) +- [ESNext (Babel)](https://babeljs.io) +- [Sass](http://sass-lang.com) +- [Less](http://lesscss.org) +- [Stylus](http://stylus-lang.com) + +And many others! Overall, webpack provides a powerful and rich API for customization that allows one to use webpack for __any stack__, while staying __non-opinionated__ about your development, testing, and production workflows. + +For a full list, see [__the list of loaders__](/loaders) or [__write your own__](/api/loaders). + + +# Why webpack + +To understand why you should use webpack let's do a recap of how we used JavaScript on the web before bundlers were a thing. + +There are two ways to run JavaScript in a browser. First, include a script for each functionality you want to implement, the issue is that the solution is hard to scale as loading too many scripts causes a network bottleneck. The other alternative is to load a big .js file containing all your project code, but this results in an unmaintainable scripts that causes problems in scope, size, readability, fragility and monolith files. + + +## IIFE's - Immediately invoked function expressions + +IIFEs solve scoping issues for large projects. When script files are wrapped by an IIFE, you can safely concatenate or safely combine files without concern of scope collision. + +This lead to tools like Make, Gulp, Grunt, Broccoli or Brunch. These tools are known as task runners and they are used, among other purposes, to concatenate all your project files together in order to solve some of the issues mentioned before. + +However, anytime you want to change one file you have to rebuild the whole thing. Concatenating makes it trivial to reuse scripts across files and makes build optimizations more difficult to implement. How do you even know what code is being used and which is not? + +If you are only using one function from lodash or one date utility from moment.js you are actually adding the entire library and just squishing it together. How do you treeshake the dependencies on your code? Also, lazy loading chunks of code can be hard to achieve at scale and requires a lot of manual work from the developer. + + +## Birth of JavaScript Modules happened thanks to Node.js + +webpack runs on Node.js, a JavaScript runtime that can be used in computers and servers outside a browser environment. + +When Node.js was released a new era started, and it came with new challenges. Now that JavaScript is not running in a browser, how are Node applications supposed to load new chunks of code? There are no html files and script tags that can be added to it. + +CommonJS came out and introduced `require`, which allows you to load and use a module in the current file. This solves scope issues out of the box and which code is used becomes clear since we need to import each module that we are going to need. + + +## npm + Node.js + modules -- mass distribution + +JavaScript is taking over the world as a language, as a platform and as a way to rapidly develop and create fast running applications. + +But there is no browser support for CommonJS. There are no [live bindings](https://medium.com/webpack/the-state-of-javascript-modules-4636d1774358). There are problems with circular references. Sync module resolution loader is slow. While CommonJS was a great solution for Node.js projects, browsers didn't support modules. That's when bundlers and tools like Browserify, RequireJS and SystemJS were created to solve this limitation making it possible to write CommonJS modules that run in a browser. + + +## ESM - ECMAScript Modules + +The good news for web projects is that modules are becoming an official feature in ECMAScript standard, though browser support is still short and early implementations show that bundling is still faster and recommended today. + + +## Wouldn't it be nice… + +...to have something that will not only let us write modules but also support any module format (at least until we get to ESM) and that can handle resources and assets at the same time? + +This is why webpack exists. It's a tool that not only let's you bundle your JavaScript applications, supporting both ESM and CommonJS, but can be extended to support all different kinds of assets like images, fonts and stylesheets. + +webpack cares a lot about performance and it's always adding and improving features like async chunk loading and prefetching to help you deliver the best possible version of your project to the user, always caring about loading times and performance. + + +# Module Resolution + +A resolver is a library which helps in locating a module by its absolute path. +A module can be required as a dependency from another module as: + +```js +import foo from 'path/to/module'; +// or +require('path/to/module'); +``` + +The dependency module can be from the application code or a third party library. The resolver helps +webpack find the module code that needs to be included in the bundle for every such `require`/`import` statement. +webpack uses [enhanced-resolve](https://github.com/webpack/enhanced-resolve) to resolve file paths while bundling modules. + + +## Resolving rules in webpack + +Using `enhanced-resolve`, webpack can resolve three kinds of file paths: + + +### Absolute paths + +```js +import '/home/me/file'; + +import 'C:\\Users\\me\\file'; +``` + +Since we already have the absolute path to the file, no further resolution is required. + + +### Relative paths + +```js +import '../src/file1'; +import './file2'; +``` + +In this case, the directory of the resource file where the `import` or `require` occurs is taken to be the context directory. The relative path specified in the `import/require` is joined to this context path to produce the absolute path to the module. + + +### Module paths + +```js +import 'module'; +import 'module/lib/file'; +``` + +Modules are searched for inside all directories specified in [`resolve.modules`](/configuration/resolve/#resolve-modules). +You can replace the original module path by an alternate path by creating an alias for it using [`resolve.alias`](/configuration/resolve/#resolve-alias) configuration option. + +Once the path is resolved based on the above rule, the resolver checks to see if the path points to a file or a directory. If the path points to a file: + +- If the path has a file extension, then the file is bundled straightaway. +- Otherwise, the file extension is resolved using the [`resolve.extensions`](/configuration/resolve/#resolve-extensions) option, which tells the resolver which extensions (eg - `.js`, `.jsx`) are acceptable for resolution. + +If the path points to a folder, then the following steps are taken to find the right file with the right extension: + +- If the folder contains a `package.json` file, then fields specified in [`resolve.mainFields`](/configuration/resolve/#resolve-mainfields) configuration option are looked up in order, and the first such field in `package.json` determines the file path. +- If there is no `package.json` or if the main fields do not return a valid path, file names specified in the [`resolve.mainFiles`](/configuration/resolve/#resolve-mainfiles) configuration option are looked for in order, to see if a matching filename exists in the imported/required directory . +- The file extension is then resolved in a similar way using the `resolve.extensions` option. + +webpack provides reasonable [defaults](/configuration/resolve) for these options depending on your build target. + + +## Resolving Loaders + +This follows the same rules as those specified for file resolution. But the [`resolveLoader`](/configuration/resolve/#resolveloader) configuration option can be used to have separate resolution rules for loaders. + + +## Caching + +Every filesystem access is cached, so that multiple parallel or serial requests to the same file occur faster. In [watch mode](/configuration/watch/#watch), only modified files are evicted from the cache. If watch mode is off, then the cache gets purged before every compilation. + + +See [Resolve API](/configuration/resolve) to learn more on the configuration options mentioned above. + + +# Dependency Graph + +Any time one file depends on another, webpack treats this as a _dependency_. This allows webpack to take non-code assets, such as images or web fonts, and also provide them as _dependencies_ for your application. + +When webpack processes your application, it starts from a list of modules defined on the command line or in its config file. +Starting from these [_entry points_](/concepts/entry-points/), webpack recursively builds a _dependency graph_ that includes every module your application needs, then bundles all of those modules into a small number of _bundles_ - often, just one - to be loaded by the browser. + +T> Bundling your application is especially powerful for _HTTP/1.1_ clients, as it minimizes the number of times your app has to wait while the browser starts a new request. For _HTTP/2_, you can also use [Code Splitting](/guides/code-splitting/) to achieve best results. + + +# Targets + +Because JavaScript can be written for both server and browser, webpack offers multiple deployment _targets_ that you can set in your webpack [configuration](/configuration). + +W> The webpack `target` property is not to be confused with the `output.libraryTarget` property. For more information see [our guide](/concepts/output/) on the `output` property. + +## Usage + +To set the `target` property, you simply set the target value in your webpack config: + +__webpack.config.js__ + +```javascript +module.exports = { + target: 'node' +}; +``` + +In the example above, using `node` webpack will compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks and not touch any built in modules like `fs` or `path`). + +Each _target_ has a variety of deployment/environment specific additions, support to fit its needs. See what [targets are available](/configuration/target/). + +?>Further expansion for other popular target values + +## Multiple Targets + +Although webpack does __not__ support multiple strings being passed into the `target` property, you can create an isomorphic library by bundling two separate configurations: + +__webpack.config.js__ + +```javascript +const path = require('path'); +const serverConfig = { + target: 'node', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'lib.node.js' + } + //… +}; + +const clientConfig = { + target: 'web', // <=== can be omitted as default is 'web' + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'lib.js' + } + //… +}; + +module.exports = [ serverConfig, clientConfig ]; +``` + +The example above will create a `lib.js` and `lib.node.js` file in your `dist` folder. + +## Resources + +As seen from the options above there are multiple different deployment _targets_ that you can choose from. Below is a list of examples, and resources that you can refer to. + +- __[compare-webpack-target-bundles](https://github.com/TheLarkInn/compare-webpack-target-bundles)__: A great resource for testing and viewing different webpack _targets_. Also great for bug reporting. +- __[Boilerplate of Electron-React Application](https://github.com/chentsulin/electron-react-boilerplate)__: A good example of a build process for electron's main process and renderer process. + +?> Need to find up to date examples of these webpack targets being used in live code or boilerplates. + + +# The Manifest + +In a typical application or site built with webpack, there are three main types of code: + +1. The source code you, and maybe your team, have written. +2. Any third-party library or "vendor" code your source is dependent on. +3. A webpack runtime and __manifest__ that conducts the interaction of all modules. + +This article will focus on the last of these three parts, the runtime and in particular the manifest. + + +## Runtime + +The runtime, along with the manifest data, is basically all the code webpack needs to connect your modularized application while it's running in the browser. It contains the loading and resolving logic needed to connect your modules as they interact. This includes connecting modules that have already been loaded into the browser as well as logic to lazy-load the ones that haven't. + + +## Manifest + +Once your application hits the browser in the form of `index.html` file, some bundles and a variety of other assets required by your application must be loaded and linked somehow. That `/src` directory you meticulously laid out is now bundled, minified and maybe even split into smaller chunks for lazy-loading by webpack's [`optimization`](/configuration/optimization/). So how does webpack manage the interaction between all of your required modules? This is where the manifest data comes in... + +As the compiler enters, resolves, and maps out your application, it keeps detailed notes on all your modules. This collection of data is called the "Manifest" and it's what the runtime will use to resolve and load modules once they've been bundled and shipped to the browser. No matter which [module syntax](/api/module-methods) you have chosen, those `import` or `require` statements have now become `__webpack_require__` methods that point to module identifiers. Using the data in the manifest, the runtime will be able to find out where to retrieve the modules behind the identifiers. + + +## The Problem + +So now you have a little bit of insight about how webpack works behind the scenes. "But, how does this affect me?", you might ask. The simple answer is that most of the time it doesn't. The runtime will do its thing, utilizing the manifest, and everything will appear to just magically work once your application hits the browser. However, if you decide to improve your projects performance by utilizing browser caching, this process will all of a sudden become an important thing to understand. + +By using content hashes within your bundle file names, you can indicate to the browser when the contents of a file has changed thus invalidating the cache. Once you start doing this though, you'll immediately notice some funny behavior. Certain hashes change even when their contents apparently do not. This is caused by the injection of the runtime and manifest which changes every build. + +See [the manifest section](/guides/output-management/#the-manifest) of our _Output management_ guide to learn how to extract the manifest, and read the guides below to learn more about the intricacies of long term caching. + + +# Hot Module Replacement + +Hot Module Replacement (HMR) exchanges, adds, or removes [modules](/concepts/modules/) while an application is running, without a full reload. This can significantly speed up development in a few ways: + +- Retain application state which is lost during a full reload. +- Save valuable development time by only updating what's changed. +- Modifications made to CSS/JS in the source code results in an instant browser update which is almost comparable to changing styles directly in the browser's dev tools. + + +## How It Works + +Let's go through some different viewpoints to understand exactly how HMR works... + +### In the Application + +The following steps allow modules to be swapped in and out of an application: + +1. The application asks the HMR runtime to check for updates. +2. The runtime asynchronously downloads the updates and notifies the application. +3. The application then asks the runtime to apply the updates. +4. The runtime synchronously applies the updates. + +You can set up HMR so that this process happens automatically, or you can choose to require user interaction for updates to occur. + + +### In the Compiler + +In addition to normal assets, the compiler needs to emit an "update" to allow updating from previous version to the new version. The "update" consists of two parts: + +1. The updated [manifest](/concepts/manifest) (JSON) +2. One or more updated chunks (JavaScript) + +The manifest contains the new compilation hash and a list of all updated chunks. Each of these chunks contains the new code for all updated modules (or a flag indicating that the module was removed). + +The compiler ensures that module IDs and chunk IDs are consistent between these builds. It typically stores these IDs in memory (e.g. with [webpack-dev-server](/configuration/dev-server/)), but it's also possible to store them in a JSON file. + + +### In a Module + +HMR is an opt-in feature that only affects modules containing HMR code. One example would be patching styling through the [`style-loader`](https://github.com/webpack-contrib/style-loader). In order for patching to work, the `style-loader` implements the HMR interface; when it receives an update through HMR, it replaces the old styles with the new ones. + +Similarly, when implementing the HMR interface in a module, you can describe what should happen when the module is updated. However, in most cases, it's not mandatory to write HMR code in every module. If a module has no HMR handlers, the update bubbles up. This means that a single handler can update a complete module tree. If a single module from the tree is updated, the entire set of dependencies is reloaded. + +See the [HMR API page](/api/hot-module-replacement) for details on the `module.hot` interface. + + +### In the Runtime + +Here things get a bit more technical... if you're not interested in the internals, feel free to jump to the [HMR API page](/api/hot-module-replacement) or [HMR guide](/guides/hot-module-replacement). + +For the module system runtime, additional code is emitted to track module `parents` and `children`. On the management side, the runtime supports two methods: `check` and `apply`. + +A `check` makes an HTTP request to the update manifest. If this request fails, there is no update available. If it succeeds, the list of updated chunks is compared to the list of currently loaded chunks. For each loaded chunk, the corresponding update chunk is downloaded. All module updates are stored in the runtime. When all update chunks have been downloaded and are ready to be applied, the runtime switches into the `ready` state. + +The `apply` method flags all updated modules as invalid. For each invalid module, there needs to be an update handler in the module or in its parent(s). Otherwise, the invalid flag bubbles up and invalidates parent(s) as well. Each bubble continues until the app's entry point or a module with an update handler is reached (whichever comes first). If it bubbles up from an entry point, the process fails. + +Afterwards, all invalid modules are disposed (via the dispose handler) and unloaded. The current hash is then updated and all `accept` handlers are called. The runtime switches back to the `idle` state and everything continues as normal. + + +## Get Started + +HMR can be used in development as a LiveReload replacement. [webpack-dev-server](/configuration/dev-server/) supports a `hot` mode in which it tries to update with HMR before trying to reload the whole page. See the [Hot Module Replacement guide](/guides/hot-module-replacement) for details. + +T> As with many other features, webpack's power lies in its customizability. There are _many_ ways of configuring HMR depending on the needs of a particular project. However, for most purposes, `webpack-dev-server` is a good fit and will allow you to get started with HMR quickly. diff --git a/src/content/configuration/_configuration_all.md b/src/content/configuration/_configuration_all.md new file mode 100644 index 000000000000..a1e52dc062a1 --- /dev/null +++ b/src/content/configuration/_configuration_all.md @@ -0,0 +1,5315 @@ + + +# Configuration + +Out of the box, webpack won't require you to use a configuration file. However, it will assume the entry point of your project is `src/index` and will output the result in `dist/main.js` minified and optimized for production. + +Usually your projects will need to extend this functionality, for this you can create a `webpack.config.js` file in the root folder and webpack will automatically use it. + +All the available configuration options are specified below. + +T> New to webpack? Check out our guide to some of webpack's [core concepts](/concepts/) to get started! + +## Options + +Click on the name of each option in the configuration code below to jump to the detailed documentation. Also note that the items with arrows can be expanded to show more examples and, in some cases, more advanced configuration. + +W> Notice that throughout the configuration we use Node's built-in [path module](https://nodejs.org/api/path.html) and prefix it with the [__dirname](https://nodejs.org/docs/latest/api/globals.html#globals_dirname) global. This prevents file path issues between operating systems and allows relative paths to work as expected. See [this section](https://nodejs.org/api/path.html#path_windows_vs_posix) for more info on POSIX vs. Windows paths. + +__webpack.config.js__ + +```js-with-links-with-details +const path = require('path'); + +module.exports = { + <details><summary>[mode](/concepts/mode): "production", // "production" | "development" | "none"</summary> + [mode](/concepts/mode): "production", // enable many optimizations for production builds + [mode](/concepts/mode): "development", // enabled useful tools for development + [mode](/concepts/mode): "none", // no defaults + </details> + // Chosen mode tells webpack to use its built-in optimizations accordingly. + <details><summary>[entry](/configuration/entry-context#entry): "./app/entry", // string | object | array</summary> + [entry](/configuration/entry-context#entry): ["./app/entry1", "./app/entry2"], + [entry](/configuration/entry-context#entry): { + a: "./app/entry-a", + b: ["./app/entry-b1", "./app/entry-b2"] + }, + </details> + // defaults to './src' + // Here the application starts executing + // and webpack starts bundling + [output](/configuration/output): { + // options related to how webpack emits results + [path](/configuration/output#output-path): path.resolve(__dirname, "dist"), // string + // the target directory for all output files + // must be an absolute path (use the Node.js path module) + <details><summary>[filename](/configuration/output#output-filename): "bundle.js", // string</summary> + [filename](/configuration/output#output-filename): "[name].js", // for multiple entry points + [filename](/configuration/output#output-filename): "[chunkhash].js", // for [long term caching](/guides/caching) + </details> + // the filename template for entry chunks + <details><summary>[publicPath](/configuration/output#output-publicpath): "/assets/", // string</summary> + [publicPath](/configuration/output#output-publicpath): "", + [publicPath](/configuration/output#output-publicpath): "https://cdn.example.com/", + </details> + // the url to the output directory resolved relative to the HTML page + [library](/configuration/output#output-library): "MyLibrary", // string, + // the name of the exported library + <details><summary>[libraryTarget](/configuration/output#output-librarytarget): "umd", // universal module definition</summary> + [libraryTarget](/configuration/output#output-librarytarget): "umd2", // universal module definition + [libraryTarget](/configuration/output#output-librarytarget): "commonjs2", // exported with module.exports + [libraryTarget](/configuration/output#output-librarytarget): "commonjs", // exported as properties to exports + [libraryTarget](/configuration/output#output-librarytarget): "amd", // defined with AMD defined method + [libraryTarget](/configuration/output#output-librarytarget): "this", // property set on this + [libraryTarget](/configuration/output#output-librarytarget): "var", // variable defined in root scope + [libraryTarget](/configuration/output#output-librarytarget): "assign", // blind assignment + [libraryTarget](/configuration/output#output-librarytarget): "window", // property set to window object + [libraryTarget](/configuration/output#output-librarytarget): "global", // property set to global object + [libraryTarget](/configuration/output#output-librarytarget): "jsonp", // jsonp wrapper + </details> + // the type of the exported library + <details><summary>/* Advanced output configuration (click to show) */</summary> + [pathinfo](/configuration/output#output-pathinfo): true, // boolean + // include useful path info about modules, exports, requests, etc. into the generated cod + [chunkFilename](/configuration/output#output-chunkfilename): "[id].js", + [chunkFilename](/configuration/output#output-chunkfilename): "[chunkhash].js", // for [long term caching](/guides/caching) + // the filename template for additional chunks + [jsonpFunction](/configuration/output#output-jsonpfunction): "myWebpackJsonp", // string + // name of the JSONP function used to load chunks + [sourceMapFilename](/configuration/output#output-sourcemapfilename): "[file].map", // string + [sourceMapFilename](/configuration/output#output-sourcemapfilename): "sourcemaps/[file].map", // string + // the filename template of the source map location + [devtoolModuleFilenameTemplate](/configuration/output#output-devtoolmodulefilenametemplate): "webpack:///[resource-path]", // string + // the name template for modules in a devtool + [devtoolFallbackModuleFilenameTemplate](/configuration/output#output-devtoolfallbackmodulefilenametemplate): "webpack:///[resource-path]?[hash]", // string + // the name template for modules in a devtool (used for conflicts) + [umdNamedDefine](/configuration/output#output-umdnameddefine): true, // boolean + // use a named AMD module in UMD library + [crossOriginLoading](/configuration/output#output-crossoriginloading): "use-credentials", // enum + [crossOriginLoading](/configuration/output#output-crossoriginloading): "anonymous", + [crossOriginLoading](/configuration/output#output-crossoriginloading): false, + // specifies how cross origin request are issued by the runtime + <details><summary>/* Expert output configuration (on own risk) */</summary> + [devtoolLineToLine](/configuration/output#output-devtoollinetoline): { + test: /\.jsx$/ + }, + // use a simple 1:1 mapped SourceMaps for these modules (faster) + [hotUpdateMainFilename](/configuration/output#output-hotupdatemainfilename): "[hash].hot-update.json", // string + // filename template for HMR manifest + [hotUpdateChunkFilename](/configuration/output#output-hotupdatechunkfilename): "[id].[hash].hot-update.js", // string + // filename template for HMR chunks + [sourcePrefix](/configuration/output#output-sourceprefix): "\t", // string + // prefix module sources in bundle for better readablitity + </details> + </details> + }, + [module](/configuration/module): { + // configuration regarding modules + [rules](/configuration/module#module-rules): [ + // rules for modules (configure loaders, parser options, etc.) + { + [test](/configuration/module#rule-test): /\.jsx?$/, + [include](/configuration/module#rule-include): [ + path.resolve(__dirname, "app") + ], + [exclude](/configuration/module#rule-exclude): [ + path.resolve(__dirname, "app/demo-files") + ], + // these are matching conditions, each accepting a regular expression or string + // test and include have the same behavior, both must be matched + // exclude must not be matched (takes preference over test and include) + // Best practices: + // - Use RegExp only in test and for filename matching + // - Use arrays of absolute paths in include and exclude + // - Try to avoid exclude and prefer include + [issuer](/configuration/module#rule-issuer): { test, include, exclude }, + // conditions for the issuer (the origin of the import) + [enforce](/configuration/module#rule-enforce): "pre", + [enforce](/configuration/module#rule-enforce): "post", + // flags to apply these rules, even if they are overridden (advanced option) + [loader](/configuration/module#rule-loader): "babel-loader", + // the loader which should be applied, it'll be resolved relative to the context + // -loader suffix is no longer optional in webpack2 for clarity reasons + // see [webpack 1 upgrade guide](/migrate/3/#automatic-loader-module-name-extension-removed) + [options](/configuration/module#rule-options-rule-query): { + presets: ["es2015"] + }, + // options for the loader + }, + { + [test](/configuration/module#rule-test): /\.html$/, + [use](/configuration/module#rule-use): [ + // apply multiple loaders and options + "htmllint-loader", + { + loader: "html-loader", + options: { + /* ... */ + } + } + ] + }, + { [oneOf](/configuration/module#rule-oneof): [ /* rules */ ] }, + // only use one of these nested rules + { [rules](/configuration/module#rule-rules): [ /* rules */ ] }, + // use all of these nested rules (combine with conditions to be useful) + { [resource](/configuration/module#rule-resource): { [and](/configuration/module#condition): [ /* conditions */ ] } }, + // matches only if all conditions are matched + { [resource](/configuration/module#rule-resource): { [or](/configuration/module#condition): [ /* conditions */ ] } }, + { [resource](/configuration/module#rule-resource): [ /* conditions */ ] }, + // matches if any condition is matched (default for arrays) + { [resource](/configuration/module#rule-resource): { [not](/configuration/module#condition): /* condition */ } } + // matches if the condition is not matched + ], + <details><summary>/* Advanced module configuration (click to show) */</summary> + [noParse](/configuration/module#module-noparse): [ + /special-library\.js$/ + ], + // do not parse this module + unknownContextRequest: ".", + unknownContextRecursive: true, + unknownContextRegExp: /^\.\/.*$/, + unknownContextCritical: true, + exprContextRequest: ".", + exprContextRegExp: /^\.\/.*$/, + exprContextRecursive: true, + exprContextCritical: true, + wrappedContextRegExp: /.*/, + wrappedContextRecursive: true, + wrappedContextCritical: false, + // specifies default behavior for dynamic requests + </details> + }, + [resolve](/configuration/resolve): { + // options for resolving module requests + // (does not apply to resolving to loaders) + [modules](/configuration/resolve#resolve-modules): [ + "node_modules", + path.resolve(__dirname, "app") + ], + // directories where to look for modules + [extensions](/configuration/resolve#resolve-extensions): [".js", ".json", ".jsx", ".css"], + // extensions that are used + [alias](/configuration/resolve#resolve-alias): { + // a list of module name aliases + "module": "new-module", + // alias "module" -> "new-module" and "module/path/file" -> "new-module/path/file" + "only-module$": "new-module", + // alias "only-module" -> "new-module", but not "only-module/path/file" -> "new-module/path/file" + "module": path.resolve(__dirname, "app/third/module.js"), + // alias "module" -> "./app/third/module.js" and "module/file" results in error + // modules aliases are imported relative to the current context + }, + <details><summary>/* alternative alias syntax (click to show) */</summary> + [alias](/configuration/resolve#resolve-alias): [ + { + name: "module", + // the old request + alias: "new-module", + // the new request + onlyModule: true + // if true only "module" is aliased + // if false "module/inner/path" is also aliased + } + ], + </details> + <details><summary>/* Advanced resolve configuration (click to show) */</summary> + [symlinks](/configuration/resolve#resolve-symlinks): true, + // follow symlinks to new location + [descriptionFiles](/configuration/resolve#resolve-descriptionfiles): ["package.json"], + // files that are read for package description + [mainFields](/configuration/resolve#resolve-mainfields): ["main"], + // properties that are read from description file + // when a folder is requested + [aliasFields](/configuration/resolve#resolve-aliasfields): ["browser"], + // properties that are read from description file + // to alias requests in this package + [enforceExtension](/configuration/resolve#resolve-enforceextension): false, + // if true request must not include an extensions + // if false request may already include an extension + [moduleExtensions](/configuration/resolve#resolveloader-moduleextensions): ["-module"], + [enforceModuleExtension](/configuration/resolve#resolve-enforcemoduleextension): false, + // like extensions/enforceExtension but for module names instead of files + [unsafeCache](/configuration/resolve#resolve-unsafecache): true, + [unsafeCache](/configuration/resolve#resolve-unsafecache): {}, + // enables caching for resolved requests + // this is unsafe as folder structure may change + // but performance improvement is really big + [cachePredicate](/configuration/resolve#resolve-cachepredicate): (path, request) => true, + // predicate function which selects requests for caching + [plugins](/configuration/resolve#resolve-plugins): [ + // ... + ] + // additional plugins applied to the resolver + </details> + }, + [performance](/configuration/performance): { + <details><summary>[hints](/configuration/performance#performance-hints): "warning", // enum </summary> + [hints](/configuration/performance#performance-hints): "error", // emit errors for perf hints + [hints](/configuration/performance#performance-hints): false, // turn off perf hints + </details> + [maxAssetSize](/configuration/performance#performance-maxassetsize): 200000, // int (in bytes), + [maxEntrypointSize](/configuration/performance#performance-maxentrypointsize): 400000, // int (in bytes) + [assetFilter](/configuration/performance#performance-assetfilter): function(assetFilename) { + // Function predicate that provides asset filenames + return assetFilename.endsWith('.css') || assetFilename.endsWith('.js'); + } + }, + <details><summary>[devtool](/configuration/devtool): "source-map", // enum </summary> + [devtool](/configuration/devtool): "inline-source-map", // inlines SourceMap into original file + [devtool](/configuration/devtool): "eval-source-map", // inlines SourceMap per module + [devtool](/configuration/devtool): "hidden-source-map", // SourceMap without reference in original file + [devtool](/configuration/devtool): "cheap-source-map", // cheap-variant of SourceMap without module mappings + [devtool](/configuration/devtool): "cheap-module-source-map", // cheap-variant of SourceMap with module mappings + [devtool](/configuration/devtool): "eval", // no SourceMap, but named modules. Fastest at the expense of detail. + </details> + // enhance debugging by adding meta info for the browser devtools + // source-map most detailed at the expense of build speed. + [context](/configuration/entry-context#context): __dirname, // string (absolute path!) + // the home directory for webpack + // the [entry](/configuration/entry-context) and [module.rules.loader](/configuration/module#rule-loader) option + // is resolved relative to this directory + <details><summary>[target](/configuration/target): "web", // enum</summary> + [target](/configuration/target): "webworker", // WebWorker + [target](/configuration/target): "node", // Node.js via require + [target](/configuration/target): "async-node", // Node.js via fs and vm + [target](/configuration/target): "node-webkit", // nw.js + [target](/configuration/target): "electron-main", // electron, main process + [target](/configuration/target): "electron-renderer", // electron, renderer process + [target](/configuration/target): (compiler) => { /* ... */ }, // custom + </details> + // the environment in which the bundle should run + // changes chunk loading behavior and available modules + <details><summary>[externals](/configuration/externals): ["react", /^@angular\//],</summary> + [externals](/configuration/externals): "react", // string (exact match) + [externals](/configuration/externals): /^[a-z\-]+($|\/)/, // Regex + [externals](/configuration/externals): { // object + angular: "this angular", // this["angular"] + react: { // UMD + commonjs: "react", + commonjs2: "react", + amd: "react", + root: "React" + } + }, + [externals](/configuration/externals): (request) => { /* ... */ return "commonjs " + request } + </details> + // Don't follow/bundle these modules, but request them at runtime from the environment + [serve](https://github.com/webpack-contrib/webpack-serve#options): { //object + port: 1337, + content: './dist', + // ... + }, + // lets you provide options for webpack-serve + <details><summary>[stats](/configuration/stats): "errors-only",</summary> + [stats](/configuration/stats): { //object + assets: true, + colors: true, + errors: true, + errorDetails: true, + hash: true, + // ... + }, + </details> + // lets you precisely control what bundle information gets displayed + [devServer](/configuration/dev-server): { + proxy: { // proxy URLs to backend development server + '/api': 'http://localhost:3000' + }, + contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location + compress: true, // enable gzip compression + historyApiFallback: true, // true for index.html upon 404, object for multiple paths + hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin + https: false, // true for self-signed, object for cert authority + noInfo: true, // only errors & warns on hot reload + // ... + }, + [plugins](plugins): [ + // ... + ], + // list of additional plugins + <details><summary>/* Advanced configuration (click to show) */</summary> + [resolveLoader](/configuration/resolve#resolveloader): { /* same as resolve */ } + // separate resolve options for loaders + [parallelism](other-options#parallelism): 1, // number + // limit the number of parallel processed modules + [profile](other-options#profile): true, // boolean + // capture timing information + [bail](other-options#bail): true, //boolean + // fail out on the first error instead of tolerating it. + [cache](other-options#cache): false, // boolean + // disable/enable caching + [watch](watch#watch): true, // boolean + // enables watching + [watchOptions](watch#watchoptions): { + [aggregateTimeout](watch#watchoptions-aggregatetimeout): 1000, // in ms + // aggregates multiple changes to a single rebuild + [poll](watch#watchoptions-poll): true, + [poll](watch#watchoptions-poll): 500, // interval in ms + // enables polling mode for watching + // must be used on filesystems that doesn't notify on change + // i. e. nfs shares + }, + [node](node): { + // Polyfills and mocks to run Node.js- + // environment code in non-Node environments. + [console](node#node-console): false, // boolean | "mock" + [global](node#node-global): true, // boolean | "mock" + [process](node#node-process): true, // boolean + [__filename](node#node-__filename): "mock", // boolean | "mock" + [__dirname](node#node-__dirname): "mock", // boolean | "mock" + [Buffer](node#node-buffer): true, // boolean | "mock" + [setImmediate](node#node-setimmediate): true // boolean | "mock" | "empty" + }, + [recordsPath](other-options#recordspath): path.resolve(__dirname, "build/records.json"), + [recordsInputPath](other-options#recordsinputpath): path.resolve(__dirname, "build/records.json"), + [recordsOutputPath](other-options#recordsoutputpath): path.resolve(__dirname, "build/records.json"), + // TODO + </details> +} +``` + +## Use custom configuration file + +If for some reason you want to use custom configuration file depending on certain situations you can change this via command line by using the `--config` flag. + +__package.json__ + +```json +"scripts": { + "build": "webpack --config prod.config.js" +} +``` + +## Configuration file generators + +Want to rapidly generate webpack configuration file for your project requirements with few clicks away? + +[Generate Custom Webpack Configuration](https://generatewebpackconfig.netlify.com/) is an interactive portal you can play around by selecting custom webpack configuration options tailored for your frontend project. It automatically generates a minimal webpack configuration based on your selection of loaders/plugins, etc. + +[Visual tool for creating webpack configs](https://webpack.jakoblind.no/) is an online configuration tool for creating webpack configuration file where you can select any combination of features you need. It also generates a full example project based on your webpack configs. + + +# Configuration Languages + +webpack accepts configuration files written in multiple programming and data languages. The list of supported file extensions can be found at the [node-interpret](https://github.com/js-cli/js-interpret) package. Using [node-interpret](https://github.com/js-cli/js-interpret), webpack can handle many different types of configuration files. + + +## TypeScript + +To write the webpack configuration in [TypeScript](http://www.typescriptlang.org/), you would first install the necessary dependencies, i.e., TypeScript and the relevant type definitions from the [DefinitelyTyped](https://definitelytyped.org/) project: + +``` bash +npm install --save-dev typescript ts-node @types/node @types/webpack +# and, if using webpack-dev-server +npm install --save-dev @types/webpack-dev-server +``` + +and then proceed to write your configuration: + +__webpack.config.ts__ + +```typescript +import path from 'path'; +import webpack from 'webpack'; + +const config: webpack.Configuration = { + mode: 'production', + entry: './foo.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'foo.bundle.js' + } +}; + +export default config; +``` + +Above sample assumes version >= 2.7 or newer of TypeScript is used with the new `esModuleInterop` and `allowSyntheticDefaultImports` compiler options in your `tsconfig.json` file. + +Note that you'll also need to check your `tsconfig.json` file. If the module in `compilerOptions` in `tsconfig.json` is `commonjs`, the setting is complete, else webpack will fail with an error. This occurs because `ts-node` does not support any module syntax other than `commonjs`. + +There are two solutions to this issue: + +- Modify `tsconfig.json`. +- Install `tsconfig-paths`. + +The __first option__ is to open your `tsconfig.json` file and look for `compilerOptions`. Set `target` to `"ES5"` and `module` to `"CommonJS"` (or completely remove the `module` option). + +The __second option__ is to install the `tsconfig-paths` package: + +``` bash +npm install --save-dev tsconfig-paths +``` + +And create a separate TypeScript configuration specifically for your webpack configs: + +__tsconfig-for-webpack-config.json__ + +``` json +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "esModuleInterop": true + } +} +``` + +T> `ts-node` can resolve a `tsconfig.json` file using the environment variable provided by `tsconfig-path`. + +Then set the environment variable `process.env.TS_NODE_PROJECT` provided by `tsconfig-path` like so: + +__package.json__ + +```json +{ + "scripts": { + "build": "TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack" + } +} +``` + + +## CoffeeScript + +Similarly, to use [CoffeeScript](http://coffeescript.org/), you would first install the necessary dependencies: + +``` bash +npm install --save-dev coffee-script +``` + +and then proceed to write your configuration: + +__webpack.config.coffee__ + +<!-- eslint-skip --> + +```js +HtmlWebpackPlugin = require('html-webpack-plugin') +webpack = require('webpack') +path = require('path') + +config = + mode: 'production' + entry: './path/to/my/entry/file.js' + output: + path: path.resolve(__dirname, 'dist') + filename: 'my-first-webpack.bundle.js' + module: rules: [ { + test: /\.(js|jsx)$/ + use: 'babel-loader' + } ] + plugins: [ + new HtmlWebpackPlugin(template: './src/index.html') + ] + +module.exports = config +``` + + +## Babel and JSX + +In the example below JSX (React JavaScript Markup) and Babel are used to create a JSON Configuration that webpack can understand. + +> Courtesy of [Jason Miller](https://twitter.com/_developit/status/769583291666169862) + +First install the necessary dependencies: + +``` bash +npm install --save-dev babel-register jsxobj babel-preset-es2015 +``` + +__.babelrc__ + +``` json +{ + "presets": [ "es2015" ] +} +``` + +__webpack.config.babel.js__ + +``` js +import jsxobj from 'jsxobj'; + +// example of an imported plugin +const CustomPlugin = config => ({ + ...config, + name: 'custom-plugin' +}); + +export default ( + <webpack target="web" watch mode="production"> + <entry path="src/index.js" /> + <resolve> + <alias {...{ + react: 'preact-compat', + 'react-dom': 'preact-compat' + }} /> + </resolve> + <plugins> + <CustomPlugin foo="bar" /> + </plugins> + </webpack> +); +``` + +W> If you are using Babel elsewhere and have `modules` set to `false`, you will have to either maintain two separate `.babelrc` files or use `const jsxobj = require('jsxobj');` and `module.exports` instead of the new `import` and `export` syntax. This is because while Node does support many new ES6 features, they don't yet support ES6 module syntax. + + +# Configuration Types + +Besides exporting a single config object, there are a few more ways that cover other needs as well. + + +## Exporting a Function + +Eventually you will find the need to disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production). You have (at least) two options: + +One option is to export a function from your webpack config instead of exporting an object. The function will be invoked with two arguments: + +- An environment as the first parameter. See the [environment options CLI documentation](/api/cli#environment-options) for syntax examples. +- An options map (`argv`) as the second parameter. This describes the options passed to webpack, with keys such as [`output-filename`](/api/cli/#output-options) and [`optimize-minimize`](/api/cli/#optimize-options). + +```diff +-module.exports = { ++module.exports = function(env, argv) { ++ return { ++ mode: env.production ? 'production' : 'development', ++ devtool: env.production ? 'source-maps' : 'eval', + plugins: [ + new TerserPlugin({ + terserOptions: { ++ compress: argv['optimize-minimize'] // only if -p or --optimize-minimize were passed + } + }) + ] ++ }; +}; +``` + + +## Exporting a Promise + +webpack will run the function exported by the configuration file and wait for a Promise to be returned. Handy when you need to asynchronously load configuration variables. + +```js +module.exports = () => { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve({ + entry: './app.js', + /* ... */ + }); + }, 5000); + }); +}; +``` + + +## Exporting multiple configurations + +Instead of exporting a single configuration object/function, you may export multiple configurations (multiple functions are supported since webpack 3.1.0). When running webpack, all configurations are built. For instance, this is useful for [bundling a library](/guides/author-libraries) for multiple [targets](/configuration/output#output-librarytarget) such as AMD and CommonJS: + +```js +module.exports = [{ + output: { + filename: './dist-amd.js', + libraryTarget: 'amd' + }, + name: 'amd', + entry: './app.js', + mode: 'production', +}, { + output: { + filename: './dist-commonjs.js', + libraryTarget: 'commonjs' + }, + name: 'commonjs', + entry: './app.js', + mode: 'production', +}]; +``` + +T> If you pass a name to [`--config-name`](/api/cli/#config-options) flag, webpack will only build that specific configuration. + + +# Entry and Context + +The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. + + +## `context` + +`string` + +The base directory, an __absolute path__, for resolving entry points and loaders from configuration. + +``` js +module.exports = { + //... + context: path.resolve(__dirname, 'app') +}; +``` + +By default the current directory is used, but it's recommended to pass a value in your configuration. This makes your configuration independent from CWD (current working directory). + +--- + + +## `entry` + +`string | [string] | object { <key>: string | [string] } | (function: () => string | [string] | object { <key>: string | [string] })` + +The point or points to enter the application. At this point the application starts executing. If an array is passed all items will be executed. + +A dynamically loaded module is __not__ an entry point. + +Simple rule: one entry point per HTML page. SPA: one entry point, MPA: multiple entry points. + +```js +module.exports = { + //... + entry: { + home: './home.js', + about: './about.js', + contact: './contact.js' + } +}; +``` + + +### Naming + +If a string or array of strings is passed, the chunk is named `main`. If an object is passed, each key is the name of a chunk, and the value describes the entry point for the chunk. + + +### Dynamic entry + +If a function is passed then it will be invoked on every [make](/api/compiler-hooks/#make) event. + +> Note that the make event triggers when webpack starts and for every invalidation when [watching for file changes](/configuration/watch/). + +```js +module.exports = { + //... + entry: () => './demo' +}; +``` + +or + +```js +module.exports = { + //... + entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])) +}; +``` + +For example: you can use dynamic entries to get the actual entries from an external source (remote server, file system content or database): + +__webpack.config.js__ + +``` js +module.exports = { + entry() { + return fetchPathsFromSomeExternalSource(); // returns a promise that will be resolved with something like ['src/main-layout.js', 'src/admin-layout.js'] + } +}; +``` + +When combining with the [`output.library`](/configuration/output#output-library) option: If an array is passed only the last item is exported. + + +# Output + +The top-level `output` key contains set of options instructing webpack on how and where it should output your bundles, assets and anything else you bundle or load with webpack. + + +## `output.auxiliaryComment` + +`string` `object` + +When used in tandem with [`output.library`](#output-library) and [`output.libraryTarget`](#output-librarytarget), this option allows users to insert comments within the export wrapper. To insert the same comment for each `libraryTarget` type, set `auxiliaryComment` to a string: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + library: 'someLibName', + libraryTarget: 'umd', + filename: 'someLibName.js', + auxiliaryComment: 'Test Comment' + } +}; +``` + +which will yield the following: + +__webpack.config.js__ + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + // Test Comment + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require('lodash')); + // Test Comment + else if(typeof define === 'function' && define.amd) + define(['lodash'], factory); + // Test Comment + else if(typeof exports === 'object') + exports['someLibName'] = factory(require('lodash')); + // Test Comment + else + root['someLibName'] = factory(root['_']); +})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { + // ... +}); +``` + +For fine-grained control over each `libraryTarget` comment, pass an object: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + //... + auxiliaryComment: { + root: 'Root Comment', + commonjs: 'CommonJS Comment', + commonjs2: 'CommonJS2 Comment', + amd: 'AMD Comment' + } + } +}; +``` + + +## `output.chunkFilename` + +`string` + +This option determines the name of non-entry chunk files. See [`output.filename`](#output-filename) option for details on the possible values. + +Note that these filenames need to be generated at runtime to send the requests for chunks. Because of this, placeholders like `[name]` and `[chunkhash]` need to add a mapping from chunk id to placeholder value to the output bundle with the webpack runtime. This increases the size and may invalidate the bundle when placeholder value for any chunk changes. + +By default `[id].js` is used or a value inferred from [`output.filename`](#output-filename) (`[name]` is replaced with `[id]` or `[id].` is prepended). + + +## `output.chunkLoadTimeout` + +`integer` + +Number of milliseconds before chunk request expires, defaults to 120 000. This option is supported since webpack 2.6.0. + + +## `output.crossOriginLoading` + +`boolean` `string` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks, by adding script tags. + +Enable [cross-origin](https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-crossorigin) loading of chunks. The following values are accepted... + +`crossOriginLoading: false` - Disable cross-origin loading (default) + +`crossOriginLoading: 'anonymous'` - Enable cross-origin loading __without credentials__ + +`crossOriginLoading: 'use-credentials'` - Enable cross-origin loading __with credentials__ + + +## `output.jsonpScriptType` + +`string` + +Allows customization of the `script` type webpack injects `script` tags into the DOM to download async chunks. The following options are available: + +- `'text/javascript'` (default) +- `'module'`: Use with ES6 ready code. + + +## `output.devtoolFallbackModuleFilenameTemplate` + +`string | function(info)` + +A fallback used when the template string or function above yields duplicates. + +See [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). + + +## `output.devtoolLineToLine` + +`boolean | object` + +> Avoid using this option as it is __deprecated__ and will soon be removed. + +Enables line to line mapping for all or some modules. This produces a simple source map where each line of the generated source is mapped to the same line of the original source. This is a performance optimization and should only be used if all input lines match generated lines. + +Pass a boolean to enable or disable this feature for all modules (defaults to `false`). An object with `test`, `include`, `exclude` is also allowed. For example, to enable this feature for all javascript files within a certain directory: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + devtoolLineToLine: { test: /\.js$/, include: 'src/utilities' } + } +}; +``` + + +## `output.devtoolModuleFilenameTemplate` + +`string | function(info)` + +This option is only used when [`devtool`](/configuration/devtool) uses an options which requires module names. + +Customize the names used in each source map's `sources` array. This can be done by passing a template string or function. For example, when using `devtool: 'eval'`, this is the default: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + devtoolModuleFilenameTemplate: 'webpack://[namespace]/[resource-path]?[loaders]' + } +}; +``` + +The following substitutions are available in template strings (via webpack's internal [`ModuleFilenameHelpers`](https://github.com/webpack/webpack/blob/master/lib/ModuleFilenameHelpers.js)): + +| Template | Description | +| ------------------------ | ----------- | +| [absolute-resource-path] | The absolute filename | +| [all-loaders] | Automatic and explicit loaders and params up to the name of the first loader | +| [hash] | The hash of the module identifier | +| [id] | The module identifier | +| [loaders] | Explicit loaders and params up to the name of the first loader | +| [resource] | The path used to resolve the file and any query params used on the first loader | +| [resource-path] | The path used to resolve the file without any query params | +| [namespace] | The modules namespace. This is usually the library name when building as a library, empty otherwise | + +When using a function, the same options are available camel-cased via the `info` parameter: + +```javascript +module.exports = { + //... + output: { + devtoolModuleFilenameTemplate: info => { + return `webpack:///${info.resourcePath}?${info.loaders}`; + } + } +}; +``` + +If multiple modules would result in the same name, [`output.devtoolFallbackModuleFilenameTemplate`](#output-devtoolfallbackmodulefilenametemplate) is used instead for these modules. + + +## `output.devtoolNamespace` + +`string` + +This option determines the modules namespace used with the [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). When not specified, it will default to the value of: [`output.library`](#output-library). It's used to prevent source file path collisions in source maps when loading multiple libraries built with webpack. + +For example, if you have 2 libraries, with namespaces `library1` and `library2`, which both have a file `./src/index.js` (with potentially different contents), they will expose these files as `webpack://library1/./src/index.js` and `webpack://library2/./src/index.js`. + + +## `output.filename` + +`string` `function` + +This option determines the name of each output bundle. The bundle is written to the directory specified by the [`output.path`](#output-path) option. + +For a single [`entry`](/configuration/entry-context#entry) point, this can be a static name. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: 'bundle.js' + } +}; +``` + +However, when creating multiple bundles via more than one entry point, code splitting, or various plugins, you should use one of the following substitutions to give each bundle a unique name... + +Using entry name: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[name].bundle.js' + } +}; +``` + +Using internal chunk id: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[id].bundle.js' + } +}; +``` + +Using the unique hash generated for every build: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[name].[hash].bundle.js' + } +}; +``` + +Using hashes based on each chunks' content: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[chunkhash].bundle.js' + } +}; +``` + +Using hashes generated for extracted content: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[contenthash].bundle.css' + } +}; +``` + +Using function to return the filename: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: (chunkData) => { + return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js'; + }, + } +}; +``` + +Make sure to read the [Caching guide](/guides/caching) for details. There are more steps involved than just setting this option. + +Note this option is called filename but you are still allowed to use something like `'js/[name]/bundle.js'` to create a folder structure. + +Note this option does not affect output files for on-demand-loaded chunks. For these files the [`output.chunkFilename`](#output-chunkfilename) option is used. Files created by loaders also aren't affected. In this case you would have to try the specific loader's available options. + +The following substitutions are available in template strings (via webpack's internal [`TemplatedPathPlugin`](https://github.com/webpack/webpack/blob/master/lib/TemplatedPathPlugin.js)): + +| Template | Description | +| ----------- | ----------------------------------------------------------------------------------- | +| [hash] | The hash of the module identifier | +| [chunkhash] | The hash of the chunk content | +| [name] | The module name | +| [id] | The module identifier | +| [query] | The module query, i.e., the string following `?` in the filename | +| [function] | The function, which can return filename [string] | + +The lengths of `[hash]` and `[chunkhash]` can be specified using `[hash:16]` (defaults to 20). Alternatively, specify [`output.hashDigestLength`](#output-hashdigestlength) to configure the length globally. + +If using a function for this option, the function will be passed an object containing the substitutions in the table above. + +T> When using the [`ExtractTextWebpackPlugin`](/plugins/extract-text-webpack-plugin), use `[contenthash]` to obtain a hash of the extracted file (neither `[hash]` nor `[chunkhash]` work). + + +## `output.hashDigest` + +The encoding to use when generating the hash, defaults to `'hex'`. All encodings from Node.JS' [`hash.digest`](https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding) are supported. Using `'base64'` for filenames might be problematic since it has the character `/` in its alphabet. Likewise `'latin1'` could contain any character. + + +## `output.hashDigestLength` + +The prefix length of the hash digest to use, defaults to `20`. + + +## `output.hashFunction` + +`string|function` + +The hashing algorithm to use, defaults to `'md4'`. All functions from Node.JS' [`crypto.createHash`](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options) are supported. Since `4.0.0-alpha2`, the `hashFunction` can now be a constructor to a custom hash function. You can provide a non-crypto hash function for performance reasons. + +```javascript +module.exports = { + //... + output: { + hashFunction: require('metrohash').MetroHash64 + } +}; +``` + +Make sure that the hashing function will have `update` and `digest` methods available. + +## `output.hashSalt` + +An optional salt to update the hash via Node.JS' [`hash.update`](https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding). + + +## `output.hotUpdateChunkFilename` + +`string` `function` + +Customize the filenames of hot update chunks. See [`output.filename`](#output-filename) option for details on the possible values. + +The only placeholders allowed here are `[id]` and `[hash]`, the default being: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + hotUpdateChunkFilename: '[id].[hash].hot-update.js' + } +}; +``` + +Here is no need to change it. + + +## `output.hotUpdateFunction` + +`function` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading hot updates. + +A JSONP function used to asynchronously load hot-update chunks. + +For details see [`output.jsonpFunction`](#output-jsonpfunction). + + +## `output.hotUpdateMainFilename` + +`string` `function` + +Customize the main hot update filename. See [`output.filename`](#output-filename) option for details on the possible values. + +`[hash]` is the only available placeholder, the default being: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + hotUpdateMainFilename: '[hash].hot-update.json' + } +}; +``` + +Here is no need to change it. + + +## `output.jsonpFunction` + +`string` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks. + +A JSONP function name used to asynchronously load chunks or join multiple initial chunks (SplitChunksPlugin, AggressiveSplittingPlugin). + +This needs to be changed if multiple webpack runtimes (from different compilation) are used on the same webpage. + +If using the [`output.library`](#output-library) option, the library name is automatically appended. + + +## `output.library` + +`string` or `object` (since webpack 3.1.0; for `libraryTarget: 'umd'`) + +How the value of the `output.library` is used depends on the value of the [`output.libraryTarget`](#output-librarytarget) option; please refer to that section for the complete details. Note that the default option for `output.libraryTarget` is `var`, so if the following configuration option is used: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary' + } +}; +``` + +The variable `MyLibrary` will be bound with the return value of your entry file, if the resulting output is included as a script tag in an HTML page. + +W> Note that if an `array` is provided as an `entry` point, only the last module in the array will be exposed. If an `object` is provided, it can be exposed using an `array` syntax (see [this example](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) for details). + +T> Read the [authoring libraries guide](/guides/author-libraries) guide for more information on `output.library` as well as `output.libraryTarget`. + + +## `output.libraryExport` + +`string | string[]` + +Configure which module or modules will be exposed via the `libraryTarget`. It is `undefined` by default, same behaviour will be applied if you set `libraryTarget` to an empty string e.g. `''` it will export the whole (namespace) object. The examples below demonstrate the effect of this config when using `libraryTarget: 'var'`. + +The following configurations are supported: + +`libraryExport: 'default'` - The __default export of your entry point__ will be assigned to the library target: + +```javascript +// if your entry has a default export of `MyDefaultModule` +var MyDefaultModule = _entry_return_.default; +``` + +`libraryExport: 'MyModule'` - The __specified module__ will be assigned to the library target: + +```javascript +var MyModule = _entry_return_.MyModule; +``` + +`libraryExport: ['MyModule', 'MySubModule']` - The array is interpreted as a __path to a module__ to be assigned to the library target: + +```javascript +var MySubModule = _entry_return_.MyModule.MySubModule; +``` + +With the `libraryExport` configurations specified above, the resulting libraries could be utilized as such: + +```javascript +MyDefaultModule.doSomething(); +MyModule.doSomething(); +MySubModule.doSomething(); +``` + + +## `output.libraryTarget` + +`string: 'var'` + +Configure how the library will be exposed. Any one of the following options can be used. Please note that this option works in conjunction with the value assigned to [`output.library`](#output-library). For the following examples, it is assumed that this value is configured as `MyLibrary`. + +T> Note that `_entry_return_` in the example code below is the value returned by the entry point. In the bundle itself, it is the output of the function that is generated by webpack from the entry point. + +### Expose a Variable + +These options assign the return value of the entry point (e.g. whatever the entry point exported) to the name provided by `output.library` at whatever scope the bundle was included at. + +`libraryTarget: 'var'` - (default) When your library is loaded, the __return value of your entry point__ will be assigned to a variable: + +```javascript +var MyLibrary = _entry_return_; + +// In a separate script... +MyLibrary.doSomething(); +``` + +W> When using this option, an empty `output.library` will result in no assignment. + + +`libraryTarget: 'assign'` - This will generate an implied global which has the potential to reassign an existing value (use with caution). + +```javascript +MyLibrary = _entry_return_; +``` + +Be aware that if `MyLibrary` isn't defined earlier your library will be set in global scope. + +W> When using this option, an empty `output.library` will result in a broken output bundle. + + +### Expose Via Object Assignment + +These options assign the return value of the entry point (e.g. whatever the entry point exported) to a specific object under the name defined by `output.library`. + +If `output.library` is not assigned a non-empty string, the default behavior is that all properties returned by the entry point will be assigned to the object as defined for the particular `output.libraryTarget`, via the following code fragment: + +```javascript +(function(e, a) { for(var i in a) { e[i] = a[i]; } }(output.libraryTarget, _entry_return_)); +``` + +W> Note that not setting a `output.library` will cause all properties returned by the entry point to be assigned to the given object; there are no checks against existing property names. + +`libraryTarget: "this"` - The __return value of your entry point__ will be assigned to this under the property named by `output.library`. The meaning of `this` is up to you: + +```javascript +this['MyLibrary'] = _entry_return_; + +// In a separate script... +this.MyLibrary.doSomething(); +MyLibrary.doSomething(); // if this is window +``` + +`libraryTarget: 'window'` - The __return value of your entry point__ will be assigned to the `window` object using the `output.library` value. + +```javascript +window['MyLibrary'] = _entry_return_; + +window.MyLibrary.doSomething(); +``` + + +`libraryTarget: 'global'` - The __return value of your entry point__ will be assigned to the `global` object using the `output.library` value. + +```javascript +global['MyLibrary'] = _entry_return_; + +global.MyLibrary.doSomething(); +``` + + +`libraryTarget: 'commonjs'` - The __return value of your entry point__ will be assigned to the `exports` object using the `output.library` value. As the name implies, this is used in CommonJS environments. + +```javascript +exports['MyLibrary'] = _entry_return_; + +require('MyLibrary').doSomething(); +``` + +### Module Definition Systems + +These options will result in a bundle that comes with a more complete header to ensure compatibility with various module systems. The `output.library` option will take on a different meaning under the following `output.libraryTarget` options. + + +`libraryTarget: 'commonjs2'` - The __return value of your entry point__ will be assigned to the `module.exports`. As the name implies, this is used in CommonJS environments: + +```javascript +module.exports = _entry_return_; + +require('MyLibrary').doSomething(); +``` + +Note that `output.library` is omitted, thus it is not required for this particular `output.libraryTarget`. + +T> Wondering the difference between CommonJS and CommonJS2 is? While they are similar, there are some subtle differences between them that are not usually relevant in the context of webpack. (For further details, please [read this issue](https://github.com/webpack/webpack/issues/1114).) + + +`libraryTarget: 'amd'` - This will expose your library as an AMD module. + +AMD modules require that the entry chunk (e.g. the first script loaded by the `<script>` tag) be defined with specific properties, such as `define` and `require` which is typically provided by RequireJS or any compatible loaders (such as almond). Otherwise, loading the resulting AMD bundle directly will result in an error like `define is not defined`. + +So, with the following configuration... + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary', + libraryTarget: 'amd' + } +}; +``` + +The generated output will be defined with the name "MyLibrary", i.e. + +```javascript +define('MyLibrary', [], function() { + return _entry_return_; +}); +``` + +The bundle can be included as part of a script tag, and the bundle can be invoked like so: + +```javascript +require(['MyLibrary'], function(MyLibrary) { + // Do something with the library... +}); +``` + +If `output.library` is undefined, the following is generated instead. + +```javascript +define([], function() { + return _entry_return_; +}); +``` + +This bundle will not work as expected, or not work at all (in the case of the almond loader) if loaded directly with a `<script>` tag. It will only work through a RequireJS compatible asynchronous module loader through the actual path to that file, so in this case, the `output.path` and `output.filename` may become important for this particular setup if these are exposed directly on the server. + + +`libraryTarget: 'amd-require'` - This packages your output with an immediately-executed AMD `require(dependencies, factory)` wrapper. + +The `'amd-require'` target allows for the use of AMD dependencies without needing a separate later invocation. As with the `'amd'` target, this depends on the appropriate [`require` function](https://github.com/amdjs/amdjs-api/blob/master/require.md) being available in the environment in which the webpack output is loaded. + +With this target, the library name is ignored. + + +`libraryTarget: 'umd'` - This exposes your library under all the module definitions, allowing it to work with CommonJS, AMD and as global variable. Take a look at the [UMD Repository](https://github.com/umdjs/umd) to learn more. + +In this case, you need the `library` property to name your module: + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary', + libraryTarget: 'umd' + } +}; +``` + +And finally the output is: + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports['MyLibrary'] = factory(); + else + root['MyLibrary'] = factory(); +})(typeof self !== 'undefined' ? self : this, function() { + return _entry_return_; +}); +``` + +Note that omitting `library` will result in the assignment of all properties returned by the entry point be assigned directly to the root object, as documented under the [object assignment section](#expose-via-object-assignment). Example: + +```javascript +module.exports = { + //... + output: { + libraryTarget: 'umd' + } +}; +``` + +The output will be: + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else { + var a = factory(); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(typeof self !== 'undefined' ? self : this, function() { + return _entry_return_; +}); +``` + +Since webpack 3.1.0, you may specify an object for `library` for differing names per targets: + +```javascript +module.exports = { + //... + output: { + library: { + root: 'MyLibrary', + amd: 'my-library', + commonjs: 'my-common-library' + }, + libraryTarget: 'umd' + } +}; +``` + +Module proof library. + + +### Other Targets + +`libraryTarget: 'jsonp'` - This will wrap the return value of your entry point into a jsonp wrapper. + +``` javascript +MyLibrary(_entry_return_); +``` + +The dependencies for your library will be defined by the [`externals`](/configuration/externals/) config. + + +## `output.path` + +`string` + +The output directory as an __absolute__ path. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + path: path.resolve(__dirname, 'dist/assets') + } +}; +``` + +Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. + + +## `output.pathinfo` + +`boolean` + +Tells webpack to include comments in bundles with information about the contained modules. This option defaults to `true` in `development` and `false` in `production` [mode](/concepts/mode/) respectively. + +W> While the data this comments can provide is very useful during development when reading the generated code, it __should not__ be used in production. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + pathinfo: true + } +}; +``` + +Note it also adds some info about tree shaking to the generated bundle. + + +## `output.publicPath` + +`string: ''` `function` + +This is an important option when using on-demand-loading or loading external resources like images, files, etc. If an incorrect value is specified you'll receive 404 errors while loading these resources. + +This option specifies the __public URL__ of the output directory when referenced in a browser. A relative URL is resolved relative to the HTML page (or `<base>` tag). Server-relative URLs, protocol-relative URLs or absolute URLs are also possible and sometimes required, i. e. when hosting assets on a CDN. + +The value of the option is prefixed to every URL created by the runtime or loaders. Because of this __the value of this option ends with `/`__ in most cases. + +Simple rule: The URL of your [`output.path`](#output-path) from the view of the HTML page. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + path: path.resolve(__dirname, 'public/assets'), + publicPath: 'https://cdn.example.com/assets/' + } +}; +``` + +For this configuration: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + publicPath: '/assets/', + chunkFilename: '[id].chunk.js' + } +}; +``` + +A request to a chunk will look like `/assets/4.chunk.js`. + +A loader outputting HTML might emit something like this: + +```html +<link href="/assets/spinner.gif" /> +``` + +or when loading an image in CSS: + +```css +background-image: url(/assets/spinner.gif); +``` + +The webpack-dev-server also takes a hint from `publicPath`, using it to determine where to serve the output files from. + +Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. + +Examples: + +```javascript +module.exports = { + //... + output: { + // One of the below + publicPath: 'https://cdn.example.com/assets/', // CDN (always HTTPS) + publicPath: '//cdn.example.com/assets/', // CDN (same protocol) + publicPath: '/assets/', // server-relative + publicPath: 'assets/', // relative to HTML page + publicPath: '../assets/', // relative to HTML page + publicPath: '', // relative to HTML page (same directory) + } +}; +``` + +In cases where the `publicPath` of output files can't be known at compile time, it can be left blank and set dynamically at runtime in the entry file using the [free variable](https://stackoverflow.com/questions/12934929/what-are-free-variables) `__webpack_public_path__`. + +```javascript +__webpack_public_path__ = myRuntimePublicPath; + +// rest of your application entry +``` + +See [this discussion](https://github.com/webpack/webpack/issues/2776#issuecomment-233208623) for more information on `__webpack_public_path__`. + + +## `output.sourceMapFilename` + +`string` + +This option is only used when [`devtool`](/configuration/devtool) uses a SourceMap option which writes an output file. + +Configure how source maps are named. By default `'[file].map'` is used. + +The `[name]`, `[id]`, `[hash]` and `[chunkhash]` substitutions from [#output-filename](#output-filename) can be used. In addition to those, you can use substitutions listed below. The `[file]` placeholder is replaced with the filename of the original file. We recommend __only using the `[file]` placeholder__, as the other placeholders won't work when generating SourceMaps for non-chunk files. + +| Template | Description | +| -------------------------- | ----------------------------------------------------------------------------------- | +| [file] | The module filename | +| [filebase] | The module [basename](https://nodejs.org/api/path.html#path_path_basename_path_ext) | + + +## `output.sourcePrefix` + +`string` + +Change the prefix for each line in the output bundles. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + sourcePrefix: '\t' + } +}; +``` + +Note by default an empty string is used. Using some kind of indentation makes bundles look more pretty, but will cause issues with multi-line strings. + +There is no need to change it. + + +## `output.strictModuleExceptionHandling` + +`boolean` + +Tell webpack to remove a module from the module instance cache (`require.cache`) if it throws an exception when it is `require`d. + +It defaults to `false` for performance reasons. + +When set to `false`, the module is not removed from cache, which results in the exception getting thrown only on the first `require` call (making it incompatible with node.js). + +For instance, consider `module.js`: + +```javascript +throw new Error('error'); +``` + +With `strictModuleExceptionHandling` set to `false`, only the first `require` throws an exception: + +```javascript +// with strictModuleExceptionHandling = false +require('module'); // <- throws +require('module'); // <- doesn't throw +``` + +Instead, with `strictModuleExceptionHandling` set to `true`, all `require`s of this module throw an exception: + +```javascript +// with strictModuleExceptionHandling = true +require('module'); // <- throws +require('module'); // <- also throws +``` + + +## `output.umdNamedDefine` + +`boolean` + +When using `libraryTarget: "umd"`, setting: + +```javascript +module.exports = { + //... + output: { + umdNamedDefine: true + } +}; +``` + +will name the AMD module of the UMD build. Otherwise an anonymous `define` is used. + + +# Module + +These options determine how the [different types of modules](/concepts/modules) within a project will be treated. + + +## `module.noParse` + +`RegExp | [RegExp] | function | string | [string]` + +Prevent webpack from parsing any files matching the given regular expression(s). Ignored files __should not__ have calls to `import`, `require`, `define` or any other importing mechanism. This can boost build performance when ignoring large libraries. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + noParse: /jquery|lodash/, + } +}; +``` + +```javascript +module.exports = { + //... + module: { + noParse: (content) => /jquery|lodash/.test(content) + } +}; +``` + + +## `module.rules` + +`[Rule]` + +An array of [Rules](#rule) which are matched to requests when modules are created. These rules can modify how the module is created. They can apply loaders to the module, or modify the parser. + + +## Rule + +`object` + +A Rule can be separated into three parts — Conditions, Results and nested Rules. + + +### Rule Conditions + +There are two input values for the conditions: + +1. The resource: An absolute path to the file requested. It's already resolved according to the [`resolve` rules](/configuration/resolve). + +2. The issuer: An absolute path to the file of the module which requested the resource. It's the location of the import. + +__Example:__ When we `import './style.css'` within `app.js`, the resource is `/path/to/style.css` and the issuer is `/path/to/app.js`. + +In a Rule the properties [`test`](#rule-test), [`include`](#rule-include), [`exclude`](#rule-exclude) and [`resource`](#rule-resource) are matched with the resource and the property [`issuer`](#rule-issuer) is matched with the issuer. + +When using multiple conditions, all conditions must match. + +W> Be careful! The resource is the _resolved_ path of the file, which means symlinked resources are the real path _not_ the symlink location. This is good to remember when using tools that symlink packages (like `npm link`), common conditions like `/node_modules/` may inadvertently miss symlinked files. Note that you can turn off symlink resolving (so that resources are resolved to the symlink path) via [`resolve.symlinks`](/configuration/resolve#resolve-symlinks). + + +### Rule results + +Rule results are used only when the Rule condition matches. + +There are two output values of a Rule: + +1. Applied loaders: An array of loaders applied to the resource. +2. Parser options: An options object which should be used to create the parser for this module. + +These properties affect the loaders: [`loader`](#rule-loader), [`options`](#rule-options-rule-query), [`use`](#rule-use). + +For compatibility also these properties: [`query`](#rule-options-rule-query), [`loaders`](#rule-loaders). + +The [`enforce`](#rule-enforce) property affects the loader category. Whether it's a normal, pre- or post- loader. + +The [`parser`](#rule-parser) property affects the parser options. + + +## Nested rules + +Nested rules can be specified under the properties [`rules`](#rule-rules) and [`oneOf`](#rule-oneof). + +These rules are evaluated when the Rule condition matches. + + +## `Rule.enforce` + +`string` + +Possible values: `'pre' | 'post'` + +Specifies the category of the loader. No value means normal loader. + +There is also an additional category "inlined loader" which are loaders applied inline of the import/require. + +There are two phases that all loaders enter one after the other: + +1. __Pitching__ phase: the pitch method on loaders is called in the order `post, inline, normal, pre`. See [Pitching Loader](/api/loaders/#pitching-loader) for details. +2. __Normal__ phase: the normal method on loaders is executed in the order `pre, normal, inline, post`. Transformation on the source code of a module happens in this phase. + +All normal loaders can be omitted (overridden) by prefixing `!` in the request. + +All normal and pre loaders can be omitted (overridden) by prefixing `-!` in the request. + +All normal, post and pre loaders can be omitted (overridden) by prefixing `!!` in the request. + +Inline loaders and `!` prefixes should not be used as they are non-standard. They may be use by loader generated code. + + +## `Rule.exclude` + +`Rule.exclude` is a shortcut to `Rule.resource.exclude`. If you supply a `Rule.exclude` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.exclude`](#condition) for details. + + +## `Rule.include` + +`Rule.include` is a shortcut to `Rule.resource.include`. If you supply a `Rule.include` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.include`](#condition) for details. + + +## `Rule.issuer` + +A [`Condition`](#condition) to match against the module that issued the request. In the following example, the `issuer` for the `a.js` request would be the path to the `index.js` file. + +__index.js__ + +```javascript +import A from './a.js'; +``` + +This option can be used to apply loaders to the dependencies of a specific module or set of modules. + + +## `Rule.loader` + +`Rule.loader` is a shortcut to `Rule.use: [ { loader } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.loader`](#useentry) for details. + + +## `Rule.loaders` + +W> This option is __deprecated__ in favor of `Rule.use`. + +`Rule.loaders` is an alias to `Rule.use`. See [`Rule.use`](#rule-use) for details. + + +## `Rule.oneOf` + +An array of [`Rules`](#rule) from which only the first matching Rule is used when the Rule matches. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + oneOf: [ + { + resourceQuery: /inline/, // foo.css?inline + use: 'url-loader' + }, + { + resourceQuery: /external/, // foo.css?external + use: 'file-loader' + } + ] + } + ] + } +}; +``` + +## `Rule.options` / `Rule.query` + +`Rule.options` and `Rule.query` are shortcuts to `Rule.use: [ { options } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.options`](#useentry) for details. + +W> `Rule.query` is deprecated in favor of `Rule.options` and `UseEntry.options`. + + +## `Rule.parser` + +An object with parser options. All applied parser options are merged. + +Parsers may inspect these options and disable or reconfigure themselves accordingly. Most of the default plugins interpret the values as follows: + +- Setting the option to `false` disables the parser. +- Setting the option to `true` or leaving it `undefined` enables the parser. + +However, parser plugins may accept more than just a boolean. For example, the internal `NodeStuffPlugin` can accept an object instead of `true` to add additional options for a particular Rule. + +__Examples__ (parser options by the default plugins): + +```js-with-links +module.exports = { + //... + module: { + rules: [ + { + //... + parser: { + amd: false, // disable AMD + commonjs: false, // disable CommonJS + system: false, // disable SystemJS + harmony: false, // disable ES2015 Harmony import/export + requireInclude: false, // disable require.include + requireEnsure: false, // disable require.ensure + requireContext: false, // disable require.context + browserify: false, // disable special handling of Browserify bundles + requireJs: false, // disable requirejs.* + node: false, // disable __dirname, __filename, module, require.extensions, require.main, etc. + node: {...} // reconfigure [node](/configuration/node) layer on module level + } + } + ] + } +} +``` + + +## `Rule.resource` + +A [`Condition`](#condition) matched with the resource. You can either supply a `Rule.resource` option or use the shortcut options `Rule.test`, `Rule.exclude`, and `Rule.include`. See details in [`Rule` conditions](#rule-conditions). + + +## `Rule.resourceQuery` + +A [`Condition`](#condition) matched with the resource query. This option is used to test against the query section of a request string (i.e. from the question mark onwards). If you were to `import Foo from './foo.css?inline'`, the following condition would match: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + resourceQuery: /inline/, + use: 'url-loader' + } + ] + } +}; +``` + + +## `Rule.rules` + +An array of [`Rules`](#rule) that is also used when the Rule matches. + + +## `Rule.sideEffects` + +`bool` + +Indicate what parts of the module contain side effects. See [Tree Shaking](/guides/tree-shaking/#mark-the-file-as-side-effect-free) for details. + + +## `Rule.test` + +`Rule.test` is a shortcut to `Rule.resource.test`. If you supply a `Rule.test` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.test`](#condition) for details. + + +## `Rule.type` + +`string` + +Possible values: `'javascript/auto' | 'javascript/dynamic' | 'javascript/esm' | 'json' | 'webassembly/experimental'` + +`Rule.type` sets the type for a matching module. This prevents defaultRules and their default importing behaviors from occurring. For example, if you want to load a `.json` file through a custom loader, you'd need to set the `type` to `javascript/auto` to bypass webpack's built-in json importing. (See [v4.0 changelog](https://github.com/webpack/webpack/releases/tag/v4.0.0) for more details) + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + //... + { + test: /\.json$/, + type: 'javascript/auto', + loader: 'custom-json-loader' + } + ] + } +}; +``` + + +## `Rule.use` + +A list of [UseEntries](#useentry) which are applied to modules. Each entry specifies a loader to be used. + +Passing a string (i.e. `use: [ 'style-loader' ]`) is a shortcut to the loader property (i.e. `use: [ { loader: 'style-loader '} ]`). + +Loaders can be chained by passing multiple loaders, which will be applied from right to left (last to first configured). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + //... + use: [ + 'style-loader', + { + loader: 'css-loader', + options: { + importLoaders: 1 + } + }, + { + loader: 'less-loader', + options: { + noIeCompat: true + } + } + ] + } + ] + } +}; +``` + +See [UseEntry](#useentry) for details. + + +## `Condition` + +Conditions can be one of these: + +- A string: To match the input must start with the provided string. I. e. an absolute directory path, or absolute path to the file. +- A RegExp: It's tested with the input. +- A function: It's called with the input and must return a truthy value to match. +- An array of Conditions: At least one of the Conditions must match. +- An object: All properties must match. Each property has a defined behavior. + +`{ test: Condition }`: The Condition must match. The convention is to provide a RegExp or array of RegExps here, but it's not enforced. + +`{ include: Condition }`: The Condition must match. The convention is to provide a string or array of strings here, but it's not enforced. + +`{ exclude: Condition }`: The Condition must NOT match. The convention is to provide a string or array of strings here, but it's not enforced. + +`{ and: [Condition] }`: All Conditions must match. + +`{ or: [Condition] }`: Any Condition must match. + +`{ not: [Condition] }`: All Conditions must NOT match. + +__Example:__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + include: [ + path.resolve(__dirname, 'app/styles'), + path.resolve(__dirname, 'vendor/styles') + ] + } + ] + } +}; +``` + + +## `UseEntry` + +`object` + +It must have a `loader` property being a string. It is resolved relative to the configuration [`context`](/configuration/entry-context#context) with the loader resolving options ([resolveLoader](/configuration/resolve#resolveloader)). + +It can have an `options` property being a string or object. This value is passed to the loader, which should interpret it as loader options. + +For compatibility a `query` property is also possible, which is an alias for the `options` property. Use the `options` property instead. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + loader: 'css-loader', + options: { + modules: true + } + } + ] + } +}; +``` + +Note that webpack needs to generate a unique module identifier from the resource and all loaders including options. It tries to do this with a `JSON.stringify` of the options object. This is fine in 99.9% of cases, but may be not unique if you apply the same loaders with different options to the resource and the options have some stringified values. + +It also breaks if the options object cannot be stringified (i.e. circular JSON). Because of this you can have a `ident` property in the options object which is used as unique identifier. + + +## Module Contexts + +> Avoid using these options as they are __deprecated__ and will soon be removed. + +These options describe the default settings for the context created when a dynamic dependency is encountered. + +Example for an `unknown` dynamic dependency: `require`. + +Example for an `expr` dynamic dependency: `require(expr)`. + +Example for an `wrapped` dynamic dependency: `require('./templates/' + expr)`. + +Here are the available options with their [defaults](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js): + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + exprContextCritical: true, + exprContextRecursive: true, + exprContextRegExp: false, + exprContextRequest: '.', + unknownContextCritical: true, + unknownContextRecursive: true, + unknownContextRegExp: false, + unknownContextRequest: '.', + wrappedContextCritical: false, + wrappedContextRecursive: true, + wrappedContextRegExp: /.*/, + strictExportPresence: false // since webpack 2.3.0 + } +}; +``` + +T> You can use the `ContextReplacementPlugin` to modify these values for individual dependencies. This also removes the warning. + +A few use cases: + +- Warn for dynamic dependencies: `wrappedContextCritical: true`. +- `require(expr)` should include the whole directory: `exprContextRegExp: /^\.\//` +- `require('./templates/' + expr)` should not include subdirectories by default: `wrappedContextRecursive: false` +- `strictExportPresence` makes missing exports an error instead of warning + + +# Resolve + +These options change how modules are resolved. webpack provides reasonable defaults, but it is possible to change the resolving in detail. Have a look at [Module Resolution](/concepts/module-resolution) for more explanation of how the resolver works. + + +## `resolve` + +`object` + +Configure how modules are resolved. For example, when calling `import "lodash"` in ES2015, the `resolve` options can change where webpack goes to look for `"lodash"` (see [`modules`](#resolve-modules)). + + +### `resolve.alias` + +`object` + +Create aliases to `import` or `require` certain modules more easily. For example, to alias a bunch of commonly used `src/` folders: + +```js +module.exports = { + //... + resolve: { + alias: { + Utilities: path.resolve(__dirname, 'src/utilities/'), + Templates: path.resolve(__dirname, 'src/templates/') + } + } +}; +``` + +Now, instead of using relative paths when importing like so: + +```js +import Utility from '../../utilities/utility'; +``` + +you can use the alias: + +```js +import Utility from 'Utilities/utility'; +``` + +A trailing `$` can also be added to the given object's keys to signify an exact match: + +```js +module.exports = { + //... + resolve: { + alias: { + xyz$: path.resolve(__dirname, 'path/to/file.js') + } + } +}; +``` + +which would yield these results: + +```js +import Test1 from 'xyz'; // Exact match, so path/to/file.js is resolved and imported +import Test2 from 'xyz/file.js'; // Not an exact match, normal resolution takes place +``` + +The following table explains other cases: + +| `alias:` | `import "xyz"` | `import "xyz/file.js"` | +| ----------------------------------- | ------------------------------------- | ----------------------------------- | +| `{}` | `/abc/node_modules/xyz/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | error | +| `{ xyz$: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "./dir/file.js" }` | `/abc/dir/file.js` | error | +| `{ xyz$: "./dir/file.js" }` | `/abc/dir/file.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "/some/dir" }` | `/some/dir/index.js` | `/some/dir/file.js` | +| `{ xyz$: "/some/dir" }` | `/some/dir/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "./dir" }` | `/abc/dir/index.js` | `/abc/dir/file.js` | +| `{ xyz: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/modu/file.js` | +| `{ xyz$: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "modu/some/file.js" }` | `/abc/node_modules/modu/some/file.js` | error | +| `{ xyz: "modu/dir" }` | `/abc/node_modules/modu/dir/index.js` | `/abc/node_modules/dir/file.js` | +| `{ xyz: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/dir/file.js` | +| `{ xyz$: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/file.js` | + +`index.js` may resolve to another file if defined in the `package.json`. + +`/abc/node_modules` may resolve in `/node_modules` too. + + +### `resolve.aliasFields` + +`array` + +Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec). Default: + +```js +module.exports = { + //... + resolve: { + aliasFields: ['browser'] + } +}; +``` + + +### `resolve.cacheWithContext` + +`boolean` (since webpack 3.1.0) + +If unsafe cache is enabled, includes `request.context` in the cache key. This option is taken into account by the [`enhanced-resolve`](https://github.com/webpack/enhanced-resolve/) module. Since webpack 3.1.0 context in resolve caching is ignored when resolve or resolveLoader plugins are provided. This addresses a performance regression. + + +### `resolve.descriptionFiles` + +`array` + +The JSON files to use for descriptions. Default: + +```js +module.exports = { + //... + resolve: { + descriptionFiles: ['package.json'] + } +}; +``` + + +### `resolve.enforceExtension` + +`boolean` + +If `true`, it will not allow extension-less files. So by default `require('./foo')` works if `./foo` has a `.js` extension, but with this enabled only `require('./foo.js')` will work. Default: + +```js +module.exports = { + //... + resolve: { + enforceExtension: false + } +}; +``` + + +### `resolve.enforceModuleExtension` + +`boolean` + +Whether to require to use an extension for modules (e.g. loaders). Default: + +```js +module.exports = { + //... + resolve: { + enforceModuleExtension: false + } +}; +``` + + +### `resolve.extensions` + +`array` + +Automatically resolve certain extensions. This defaults to: + +```js +module.exports = { + //... + resolve: { + extensions: ['.wasm', '.mjs', '.js', '.json'] + } +}; +``` + +which is what enables users to leave off the extension when importing: + +```js +import File from '../path/to/file'; +``` + +W> Using this will __override the default array__, meaning that webpack will no longer try to resolve modules using the default extensions. For modules that are imported with their extension, e.g. `import SomeFile from "./somefile.ext"`, to be properly resolved, a string containing "\*" must be included in the array. + + +### `resolve.mainFields` + +`array` + +When importing from an npm package, e.g. `import * as D3 from "d3"`, this option will determine which fields in its `package.json` are checked. The default values will vary based upon the [`target`](/concepts/targets) specified in your webpack configuration. + +When the `target` property is set to `webworker`, `web`, or left unspecified: + + +```js +module.exports = { + //... + resolve: { + mainFields: ['browser', 'module', 'main'] + } +}; +``` + +For any other target (including `node`): + +```js +module.exports = { + //... + resolve: { + mainFields: ['module', 'main'] + } +}; +``` + +For example, the `package.json` of [D3](https://d3js.org/) contains these fields: + +```json +{ + "main": "build/d3.Node.js", + "browser": "build/d3.js", + "module": "index" +} +``` + +This means that when we `import * as D3 from "d3"` this will really resolve to the file in the `browser` property. The `browser` property takes precedence here because it's the first item in `mainFields`. Meanwhile, a Node.js application bundled by webpack will resolve by default to the file in the `module` field. + + +### `resolve.mainFiles` + +`array` + +The filename to be used while resolving directories. Default: + +```js +module.exports = { + //... + resolve: { + mainFiles: ['index'] + } +}; +``` + + +### `resolve.modules` + +`array` + +Tell webpack what directories should be searched when resolving modules. + +Absolute and relative paths can both be used, but be aware that they will behave a bit differently. + +A relative path will be scanned similarly to how Node scans for `node_modules`, by looking through the current directory as well as its ancestors (i.e. `./node_modules`, `../node_modules`, and on). + +With an absolute path, it will only search in the given directory. + +`resolve.modules` defaults to: + +```js +module.exports = { + //... + resolve: { + modules: ['node_modules'] + } +}; +``` + +If you want to add a directory to search in that takes precedence over `node_modules/`: + +```js +module.exports = { + //... + resolve: { + modules: [path.resolve(__dirname, 'src'), 'node_modules'] + } +}; +``` + + +### `resolve.unsafeCache` + +`regex` `array` `boolean` + +Enable aggressive, but __unsafe__, caching of modules. Passing `true` will cache everything. Default: + +```js +module.exports = { + //... + resolve: { + unsafeCache: true + } +}; +``` + +A regular expression, or an array of regular expressions, can be used to test file paths and only cache certain modules. For example, to only cache utilities: + +```js +module.exports = { + //... + resolve: { + unsafeCache: /src\/utilities/ + } +}; +``` + +W> Changes to cached paths may cause failure in rare cases. + + +### `resolve.plugins` + +A list of additional resolve plugins which should be applied. It allows plugins such as [`DirectoryNamedWebpackPlugin`](https://www.npmjs.com/package/directory-named-webpack-plugin). + +```js +module.exports = { + //... + resolve: { + plugins: [ + new DirectoryNamedWebpackPlugin() + ] + } +}; +``` + + +### `resolve.symlinks` + +`boolean` + +Whether to resolve symlinks to their symlinked location. + +When enabled, symlinked resources are resolved to their _real_ path, not their symlinked location. Note that this may cause module resolution to fail when using tools that symlink packages (like `npm link`). + +`resolve.symlinks` defaults to: + +```js +module.exports = { + //... + resolve: { + symlinks: true + } +}; +``` + + +### `resolve.cachePredicate` + +`function` + +A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. Default: + +```js +module.exports = { + //... + resolve: { + cachePredicate: function() { return true; } + } +}; +``` + + +## `resolveLoader` + +`object` + +This set of options is identical to the `resolve` property set above, but is used only to resolve webpack's [loader](/concepts/loaders) packages. Default: + +```js +module.exports = { + //... + resolveLoader: { + modules: [ 'node_modules' ], + extensions: [ '.js', '.json' ], + mainFields: [ 'loader', 'main' ] + } +}; +``` + +T> Note that you can use alias here and other features familiar from resolve. For example `{ txt: 'raw-loader' }` would shim `txt!templates/demo.txt` to use `raw-loader`. + + +### `resolveLoader.moduleExtensions` + +`array` + +The extensions/suffixes that are used when resolving loaders. Since version two, we [strongly recommend](/migrate/3/#automatic-loader-module-name-extension-removed) using the full name, e.g. `example-loader`, as much as possible for clarity. However, if you really wanted to exclude the `-loader` bit, i.e. just use `example`, you can use this option to do so: + +```js +module.exports = { + //... + resolveLoader: { + moduleExtensions: [ '-loader' ] + } +}; +``` + + +# Optimization + +Since version 4 webpack runs optimizations for you depending on the chosen [`mode`](/concepts/mode/), still all optimizations are available for manual configuration and overrides. + + +## `optimization.minimize` + +`boolean` + +Tell webpack to minimize the bundle using the [TerserPlugin](/plugins/terser-webpack-plugin/). + +This is `true` by default in `production` mode. + +__webpack.config.js__ + + +```js +module.exports = { + //... + optimization: { + minimize: false + } +}; +``` + +T> Learn how [mode](/concepts/mode/) works. + +## `optimization.minimizer` + +`[TerserPlugin]` + +Allows you to override the default minimizer by providing a different one or more customized [TerserPlugin](/plugins/terser-webpack-plugin/) instances. + +__webpack.config.js__ + + +```js +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + //... + optimization: { + minimizer: [ + new TerserPlugin({ /* your config */ }) + ] + } +}; +``` + +## `optimization.splitChunks` + +`object` + +By default webpack v4+ provides new common chunks strategies out of the box for dynamically imported modules. See available options for configuring this behavior in the [SplitChunksPlugin](/plugins/split-chunks-plugin/) page. + +## `optimization.runtimeChunk` + +`object` `string` `boolean` + +Setting `optimization.runtimeChunk` to `true` or `"multiple"` adds an additional chunk to each entrypoint containing only the runtime. This setting is an alias for: + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: entrypoint => `runtime~${entrypoint.name}` + } + } +}; +``` + +The value `"single"` instead creates a runtime file to be shared for all generated chunks. This setting is an alias for: + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: 'runtime' + } + } +}; +``` + +By setting `optimization.runtimeChunk` to `object` it is only possible to provide the `name` property which stands for the name or name factory for the runtime chunks. + +Default is `false`: each entry chunk embeds runtime. + +W> Imported modules are initialized for each runtime chunk separately, so if you include multiple entry points on a page, beware of this behavior. You will probably want to set it to `single` or use another configuration that allows you to only have one runtime instance. + +__webpack.config.js__ + + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: entrypoint => `runtimechunk~${entrypoint.name}` + } + } +}; +``` + +## `optimization.noEmitOnErrors` + +`boolean` + +Use the `optimization.noEmitOnErrors` to skip the emitting phase whenever there are errors while compiling. This ensures that no erroring assets are emitted. The `emitted` flag in the stats is `false` for all assets. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + noEmitOnErrors: true + } +}; +``` + +W> If you are using webpack [CLI](/api/cli/), the webpack process will not exit with an error code while this plugin is enabled. If you want webpack to "fail" when using the CLI, please check out the [`bail` option](/api/cli/#advanced-options). + +## `optimization.namedModules` + +`boolean: false` + +Tells webpack to use readable module identifiers for better debugging. When `optimization.namedModules` is not set in webpack config, webpack will enable it by default for [mode](/concepts/mode/) `development` and disable for [mode](/concepts/mode/) `production`. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + namedModules: true + } +}; +``` + +## `optimization.namedChunks` + +`boolean: false` + +Tells webpack to use readable chunk identifiers for better debugging. This option is enabled by default for [mode](/concepts/mode/) `development` and disabled for [mode](/concepts/mode/) `production` if no option is provided in webpack config. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + namedChunks: true + } +}; +``` + +## `optimization.moduleIds` + +`bool: false` `string: natural, named, hashed, size, total-size` + +Tells webpack which algorithm to use when choosing module ids. Setting `optimization.moduleIds` to `false` tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin. By default `optimization.moduleIds` is set to `false`. + +The following string values are supported: + +Option | Description +--------------------- | ----------------------- +`natural` | Numeric ids in order of usage. +`named` | Readable ids for better debugging. +`hashed` | Short hashes as ids for better long term caching. +`size` | Numeric ids focused on minimal initial download size. +`total-size` | numeric ids focused on minimal total download size. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + moduleIds: 'hashed' + } +}; +``` + +## `optimization.nodeEnv` + +`string` `bool: false` + +Tells webpack to set `process.env.NODE_ENV` to a given string value. `optimization.nodeEnv` uses [DefinePlugin](/plugins/define-plugin/) unless set to `false`. `optimization.nodeEnv` __defaults__ to [mode](/concepts/mode/) if set, else falls back to `"production"`. + +Possible values: + +- any string: the value to set `process.env.NODE_ENV` to. +- false: do not modify/set the value of `process.env.NODE_ENV`. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + nodeEnv: 'production' + } +}; +``` + +## `optimization.mangleWasmImports` + +`bool: false` + +When set to `true` tells webpack to reduce the size of WASM by changing imports to shorter strings. It mangles module and export names. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + mangleWasmImports: true + } +}; +``` + +## `optimization.removeAvailableModules` + +`bool: true` + +Tells webpack to detect and remove modules from chunks when these modules are already included in all parents. Setting `optimization.removeAvailableModules` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + removeAvailableModules: false + } +}; +``` + +## `optimization.removeEmptyChunks` + +`bool: true` + +Tells webpack to detect and remove chunks which are empty. Setting `optimization.removeEmptyChunks` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + removeEmptyChunks: false + } +}; +``` + +## `optimization.mergeDuplicateChunks` + +`bool: true` + +Tells webpack to merge chunks which contain the same modules. Setting `optimization.mergeDuplicateChunks` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + mergeDuplicateChunks: false + } +}; +``` + +## `optimization.flagIncludedChunks` + +`bool` + +Tells webpack to determine and flag chunks which are subsets of other chunks in a way that subsets don’t have to be loaded when the bigger chunk has been already loaded. By default `optimization.flagIncludedChunks` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + flagIncludedChunks: true + } +}; +``` + +## `optimization.occurrenceOrder` + +`bool` + +Tells webpack to figure out an order of modules which will result in the smallest initial bundle. By default `optimization.occurrenceOrder` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + occurrenceOrder: false + } +}; +``` + +## `optimization.providedExports` + +`bool` + +Tells webpack to figure out which exports are provided by modules to generate more efficient code for `export * from ...`. By default `optimization.providedExports` is enabled. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + providedExports: false + } +}; +``` + +## `optimization.usedExports` + +`bool` + +Tells webpack to determine used exports for each module. This depends on [`optimization.providedExports`](#optimization-occurrenceorder). Information collected by `optimization.usedExports` is used by other optimizations or code generation i.e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible. +Dead code elimination in minimizers will benefit from this and can remove unused exports. +By default `optimization.usedExports` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + usedExports: true + } +}; +``` + +## `optimization.concatenateModules` + +`bool` + +Tells webpack to find segments of the module graph which can be safely concatenated into a single module. Depends on [`optimization.providedExports`](#optimization-providedexports) and [`optimization.usedExports`](#optimization-usedexports). +By default `optimization.concatenateModules` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + concatenateModules: true + } +}; +``` + +## `optimization.sideEffects` + +`bool` + +Tells webpack to recognise the [`sideEffects`](https://github.com/webpack/webpack/blob/master/examples/side-effects/README.md) flag in `package.json` or rules to skip over modules which are flagged to contain no side effects when exports are not used. + +__package.json__ + +``` json +{ + "name": "awesome npm module", + "version": "1.0.0", + "sideEffects": false +} +``` + +T> Please note that `sideEffects` should be in the npm module's `package.json` file and doesn't mean that you need to set `sideEffects` to `false` in your own project's `package.json` which requires that big module. + +`optimization.sideEffects` depends on [`optimization.providedExports`](#optimization-providedexports) to be enabled. This dependency has a build time cost, but eliminating modules has positive impact on performance because of less code generation. Effect of this optimization depends on your codebase, try it for possible performance wins. + +By default `optimization.sideEffects` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + sideEffects: true + } +}; +``` + +## `optimization.portableRecords` + +`bool` + +`optimization.portableRecords` tells webpack to generate records with relative paths to be able to move the context folder. + +By default `optimization.portableRecords` is disabled. Automatically enabled if at least one of the records options provided to webpack config: [`recordsPath`](/configuration/other-options/#recordspath), [`recordsInputPath`](/configuration/other-options/#recordsinputpath), [`recordsOutputPath`](/configuration/other-options/#recordsoutputpath). + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + portableRecords: true + } +}; +``` + + +# Plugins + +The `plugins` option is used to customize the webpack build process in a variety of ways. webpack comes with a variety built-in plugins available under `webpack.[plugin-name]`. See [Plugins page](/plugins) for a list of plugins and documentation but note that there are a lot more out in the community. + +T> Note: This page only discusses using plugins, however if you are interested in writing your own please visit [Writing a Plugin](/development/how-to-write-a-plugin/). + + +## `plugins` + +`array` + +A list of webpack plugins. For example, [`DefinePlugin`](/plugins/define-plugin/) allows you to create global constants which can be configured at compile time. This can be useful for allowing different behavior between development builds and release builds. + +```js +module.exports = { + //... + plugins: [ + new webpack.DefinePlugin({ + // Definitions... + }) + ] +}; +``` + +A more complex example, using multiple plugins, might look something like this: + +```js +var webpack = require('webpack'); +// importing plugins that do not come by default in webpack +var ExtractTextPlugin = require('extract-text-webpack-plugin'); +var DashboardPlugin = require('webpack-dashboard/plugin'); + +// adding plugins to your configuration +module.exports = { + //... + plugins: [ + new ExtractTextPlugin({ + filename: 'build.min.css', + allChunks: true, + }), + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + // compile time plugins + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': '"production"', + }), + // webpack-dev-server enhancement plugins + new DashboardPlugin(), + new webpack.HotModuleReplacementPlugin(), + ] +}; +``` + + +# DevServer + +[webpack-dev-server](https://github.com/webpack/webpack-dev-server) can be used to quickly develop an application. See the [development guide](/guides/development/) to get started. + +This page describes the options that affect the behavior of webpack-dev-server (short: dev-server). + +T> Options that are compatible with [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) have 🔑 next to them. + + +## `devServer` + +`object` + +This set of options is picked up by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) and can be used to change its behavior in various ways. Here's a simple example that gzips and serves everything from our `dist/` directory in the project root: + +__webpack.config.js__ + +```javascript +var path = require('path'); + +module.exports = { + //... + devServer: { + contentBase: path.join(__dirname, 'dist'), + compress: true, + port: 9000 + } +}; +``` + +When the server is started, there will be a message prior to the list of resolved modules: + +```bash +http://localhost:9000/ +webpack output is served from /build/ +Content not from webpack is served from /path/to/dist/ +``` + +that will give some background on where the server is located and what it's serving. + +If you're using dev-server through the Node.js API, the options in `devServer` will be ignored. Pass the options as a second parameter instead: `new WebpackDevServer(compiler, {...})`. [See here](https://github.com/webpack/webpack-dev-server/tree/master/examples/api/simple) for an example of how to use webpack-dev-server through the Node.js API. + +W> Be aware that when [exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) only the `devServer` options for the first configuration will be taken into account and used for all the configurations in the array. + +T> If you're having trouble, navigating to the `/webpack-dev-server` route will show where files are served. For example, `http://localhost:9000/webpack-dev-server`. + +## `devServer.after` + +`function (app, server)` + +Provides the ability to execute custom middleware after all other middleware +internally within the server. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + after: function(app, server) { + // do fancy stuff + } + } +}; +``` + +## `devServer.allowedHosts` + +`array` + +This option allows you to whitelist services that are allowed to access the dev server. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + allowedHosts: [ + 'host.com', + 'subdomain.host.com', + 'subdomain2.host.com', + 'host2.com' + ] + } +}; +``` + +Mimicking django's `ALLOWED_HOSTS`, a value beginning with `.` can be used as a subdomain wildcard. `.host.com` will match `host.com`, `www.host.com`, and any other subdomain of `host.com`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + // this achieves the same effect as the first example + // with the bonus of not having to update your config + // if new subdomains need to access the dev server + allowedHosts: [ + '.host.com', + 'host2.com' + ] + } +}; +``` + +To use this option with the CLI pass the `--allowed-hosts` option a comma-delimited string. + +```bash +webpack-dev-server --entry /entry/file --output-path /output/path --allowed-hosts .host.com,host2.com +``` + +## `devServer.before` + +`function (app, server)` + +Provides the ability to execute custom middleware prior to all other middleware +internally within the server. This could be used to define custom handlers, for +example: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + before: function(app, server) { + app.get('/some/path', function(req, res) { + res.json({ custom: 'response' }); + }); + } + } +}; +``` + +## `devServer.bonjour` + +This option broadcasts the server via [ZeroConf](http://www.zeroconf.org/) networking on start + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + bonjour: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --bonjour +``` + + +## `devServer.clientLogLevel` + +`string: 'none' | 'info' | 'error' | 'warning'` + +When using _inline mode_, the console in your DevTools will show you messages e.g. before reloading, before an error or when [Hot Module Replacement](/concepts/hot-module-replacement/) is enabled. Defaults to `info`. + +`devServer.clientLogLevel` may be too verbose, you can turn logging off by setting it to `'none'`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + clientLogLevel: 'none' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --client-log-level none +``` + +## `devServer.color` - CLI only + +`boolean` + +Enables/Disables colors on the console. + +```bash +webpack-dev-server --color +``` + + +## `devServer.compress` + +`boolean` + +Enable [gzip compression](https://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/) for everything served: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + compress: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --compress +``` + + +## `devServer.contentBase` + +`boolean: false` `string` `[string]` `number` + +Tell the server where to serve content from. This is only necessary if you want to serve static files. [`devServer.publicPath`](#devserver-publicpath-) will be used to determine where the bundles should be served from, and takes precedence. + +T> It is recommended to use an absolute path. + +By default it will use your current working directory to serve content. To disable `contentBase` set it to `false`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + contentBase: path.join(__dirname, 'public') + } +}; +``` + +It is also possible to serve from multiple directories: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + contentBase: [path.join(__dirname, 'public'), path.join(__dirname, 'assets')] + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --content-base /path/to/content/dir +``` + + +## `devServer.disableHostCheck` + +`boolean` + +When set to `true` this option bypasses host checking. __THIS IS NOT RECOMMENDED__ as apps that do not check the host are vulnerable to DNS rebinding attacks. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + disableHostCheck: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --disable-host-check +``` + + +## `devServer.filename` 🔑 + +`string` + +This option lets you reduce the compilations in [lazy mode](#devserver-lazy-). +By default in [lazy mode](#devserver-lazy-), every request results in a new compilation. With `filename`, it's possible to only compile when a certain file is requested. + +If [`output.filename`](/configuration/output/#output-filename) is set to `'bundle.js'` and `devServer.filename` is used like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: 'bundle.js' + }, + devServer: { + lazy: true, + filename: 'bundle.js' + } +}; +``` + +It will now only compile the bundle when `/bundle.js` is requested. + +T> `filename` has no effect when used without [lazy mode](#devserver-lazy-). + + +## `devServer.headers` 🔑 + +`object` + +Adds headers to all responses: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + headers: { + 'X-Custom-Foo': 'bar' + } + } +}; +``` + + +## `devServer.historyApiFallback` + +`boolean` `object` + +When using the [HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/API/History), the `index.html` page will likely have to be served in place of any `404` responses. `devServer.historyApiFallback` is disabled by default. Enable it by passing: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: true + } +}; +``` + +By passing an object this behavior can be controlled further using options like `rewrites`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: { + rewrites: [ + { from: /^\/$/, to: '/views/landing.html' }, + { from: /^\/subpage/, to: '/views/subpage.html' }, + { from: /./, to: '/views/404.html' } + ] + } + } +}; +``` + +When using dots in your path (common with Angular), you may need to use the `disableDotRule`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: { + disableDotRule: true + } + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --history-api-fallback +``` + +For more options and information, see the [connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback) documentation. + + +## `devServer.host` + +`string` + +Specify a host to use. By default this is `localhost`. If you want your server to be accessible externally, specify it like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + host: '0.0.0.0' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --host 0.0.0.0 +``` + + +## `devServer.hot` + +`boolean` + +Enable webpack's [Hot Module Replacement](/concepts/hot-module-replacement/) feature: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + hot: true + } +}; +``` + +T> Note that [`webpack.HotModuleReplacementPlugin`](/plugins/hot-module-replacement-plugin/) is required to fully enable HMR. If `webpack` or `webpack-dev-server` are launched with the `--hot` option, this plugin will be added automatically, so you may not need to add this to your `webpack.config.js`. See the [HMR concepts page](/concepts/hot-module-replacement/) for more information. + + +## `devServer.hotOnly` + +`boolean` + +Enables Hot Module Replacement (see [`devServer.hot`](#devserver-hot)) without page refresh as fallback in case of build failures. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + hotOnly: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --hot-only +``` + + +## `devServer.https` + +`boolean` `object` + +By default dev-server will be served over HTTP. It can optionally be served over HTTP/2 with HTTPS: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + https: true + } +}; +``` + +With the above setting a self-signed certificate is used, but you can provide your own: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + https: { + key: fs.readFileSync('/path/to/server.key'), + cert: fs.readFileSync('/path/to/server.crt'), + ca: fs.readFileSync('/path/to/ca.pem'), + } + } +}; +``` + +This object is passed straight to Node.js HTTPS module, so see the [HTTPS documentation](https://nodejs.org/api/https.html) for more information. + +Usage via the CLI + +```bash +webpack-dev-server --https +``` + +To pass your own certificate via the CLI use the following options + +```bash +webpack-dev-server --https --key /path/to/server.key --cert /path/to/server.crt --cacert /path/to/ca.pem +``` + +## `devServer.index` + +`string` + +The filename that is considered the index file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + index: 'index.html' + } +}; +``` + + +## `devServer.info` - CLI only + +`boolean` + +Output cli information. It is enabled by default. + +```bash +webpack-dev-server --info=false +``` + + +## `devServer.inline` + +`boolean` + +Toggle between the dev-server's two different modes. By default the application will be served with _inline mode_ enabled. This means that a script will be inserted in your bundle to take care of live reloading, and build messages will appear in the browser console. + +It is also possible to use __iframe mode__, which uses an `<iframe>` under a notification bar with messages about the build. To switch to __iframe mode__: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + inline: false + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --inline=false +``` + +T> Inline mode is recommended for [Hot Module Replacement](/plugins/hot-module-replacement-plugin/) as it includes an HMR trigger from the websocket. Polling mode can be used as an alternative, but requires an additional entry point, `'webpack/hot/poll?1000'`. + + +## `devServer.lazy` 🔑 + +`boolean` + +When `devServer.lazy` is enabled, the dev-server will only compile the bundle when it gets requested. This means that webpack will not watch any file changes. We call this __lazy mode__. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + lazy: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --lazy +``` + +T> [`watchOptions`](#devserver-watchoptions-) will have no effect when used with __lazy mode__. + +T> If you use the CLI, make sure __inline mode__ is disabled. + + +## `devServer.noInfo` 🔑 + +`boolean` + +Tells dev-server to supress messages like the webpack bundle information. Errors and warnings will still be shown. `devServer.noInfo` is disabled by default. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + noInfo: true + } +}; +``` + + +## `devServer.open` + +`boolean` `string` + +Tells dev-server to open the browser after server had been started. Disabled by default. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + open: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --open +``` + +If no browser is provided (as shown above), your default browser will be used. To specify a different browser, just pass its name: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + open: 'Chrome' + } +}; +``` + +And via the CLI + +```bash +webpack-dev-server --open 'Chrome' +``` + +T> The browser application name is platform dependent. Don't hard code it in reusable modules. For example, `'Chrome'` is Google Chrome on macOS, `'google-chrome'` on Linux and `'chrome'` on Windows. + + +## `devServer.openPage` + +`string` + +Specify a page to navigate to when opening the browser. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + openPage: '/different/page' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --open-page "/different/page" +``` + + +## `devServer.overlay` + +`boolean` `object: { boolean errors, boolean warnings }` + +Shows a full-screen overlay in the browser when there are compiler errors or warnings. Disabled by default. If you want to show only compiler errors: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + overlay: true + } +}; +``` + +If you want to show warnings as well as errors: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + overlay: { + warnings: true, + errors: true + } + } +}; +``` + + +## `devServer.pfx` + +`string` + +When used via the CLI, a path to an SSL .pfx file. If used in options, it should be the bytestream of the .pfx file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + pfx: '/path/to/file.pfx' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --pfx /path/to/file.pfx +``` + + +## `devServer.pfxPassphrase` + +`string` + +The passphrase to a SSL PFX file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + pfxPassphrase: 'passphrase' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --pfx-passphrase passphrase +``` + + +## `devServer.port` + +`number` + +Specify a port number to listen for requests on: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + port: 8080 + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --port 8080 +``` + + +## `devServer.proxy` + +`object` `[object, function]` + +Proxying some URLs can be useful when you have a separate API backend development server and you want to send API requests on the same domain. + +The dev-server makes use of the powerful [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) package. Check out its [documentation](https://github.com/chimurai/http-proxy-middleware#options) for more advanced usages. Note that some of `http-proxy-middleware`'s features do not require a `target` key, e.g. its `router` feature, but you will still need to include a `target` key in your config here, otherwise `webpack-dev-server` won't pass it along to `http-proxy-middleware`). + +With a backend on `localhost:3000`, you can use this to enable proxying: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': 'http://localhost:3000' + } + } +}; +``` + +A request to `/api/users` will now proxy the request to `http://localhost:3000/api/users`. + +If you don't want `/api` to be passed along, we need to rewrite the path: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'http://localhost:3000', + pathRewrite: {'^/api' : ''} + } + } + } +}; +``` + +A backend server running on HTTPS with an invalid certificate will not be accepted by default. If you want to, modify your config like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'https://other-server.example.com', + secure: false + } + } + } +}; +``` + +Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a function. + +In the function you get access to the request, response and proxy options. It must return either `false` or a path that will be served instead of continuing to proxy the request. + +E.g. for a browser request, you want to serve a HTML page, but for an API request you want to proxy it. You could do something like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'http://localhost:3000', + bypass: function(req, res, proxyOptions) { + if (req.headers.accept.indexOf('html') !== -1) { + console.log('Skipping proxy for browser request.'); + return '/index.html'; + } + } + } + } + } +}; +``` + +If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a `context` property: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: [{ + context: ['/auth', '/api'], + target: 'http://localhost:3000', + }] + } +}; +``` + +Note that requests to root won't be proxied by default. To enable root proxying, the `devServer.index` option should be specified as a falsy value: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + index: '', // specify to enable root proxying + host: '...', + contentBase: '...', + proxy: { + context: () => true, + target: 'http://localhost:1234' + } + } +}; +``` + +The origin of the host header is kept when proxying by default, you can set `changeOrigin` to `true` to override this behaviour. It is useful in some cases like using [name-based virtual hosted sites](https://en.wikipedia.org/wiki/Virtual_hosting#Name-based). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': 'http://localhost:3000', + changeOrigin: true + } + } +}; +``` + +## `devServer.progress` - CLI only + +`boolean` + +Output running progress to console. + +```bash +webpack-dev-server --progress +``` + + +## `devServer.public` + +`string` + +When using _inline mode_ and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on `window.location`, but if that fails you'll need to use this. + +For example, the dev-server is proxied by nginx, and available on `myapp.test`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + public: 'myapp.test:80' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --public myapp.test:80 +``` + + +## `devServer.publicPath` 🔑 + +`string` + +The bundled files will be available in the browser under this path. + +Imagine that the server is running under `http://localhost:8080` and [`output.filename`](/configuration/output/#output-filename) is set to `bundle.js`. By default the `devServer.publicPath` is `'/'`, so your bundle is available as `http://localhost:8080/bundle.js`. + +Change `devServer.publicPath` to put bundle under specific directory: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + publicPath: '/assets/' + } +}; +``` + +The bundle will now be available as `http://localhost:8080/assets/bundle.js`. + +T> Make sure `devServer.publicPath` always starts and ends with a forward slash. + +It is also possible to use a full URL. This is necessary for [Hot Module Replacement](/concepts/hot-module-replacement/). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + publicPath: 'http://localhost:8080/assets/' + } +}; +``` + +The bundle will also be available as `http://localhost:8080/assets/bundle.js`. + +T> It is recommended that `devServer.publicPath` is the same as [`output.publicPath`](/configuration/output/#output-publicpath). + + +## `devServer.quiet` 🔑 + +`boolean` + +With `devServer.quiet` enabled, nothing except the initial startup information will be written to the console. This also means that errors or warnings from webpack are not visible. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + quiet: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --quiet +``` + + +## `devServer.setup` + +`function (app, server)` + +W> This option is __deprecated__ in favor of [`devServer.before`](#devserver-before) and will be removed in v3.0.0. + +Here you can access the Express app object and add your own custom middleware to it. +For example, to define custom handlers for some paths: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + setup: function(app, server) { + app.get('/some/path', function(req, res) { + res.json({ custom: 'response' }); + }); + } + } +}; +``` + + +## `devServer.socket` + +`string` + +The Unix socket to listen to (instead of a host). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + socket: 'socket' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --socket socket +``` + + +## `devServer.staticOptions` + +It is possible to configure advanced options for serving static files from `contentBase`. See the [Express documentation](http://expressjs.com/en/4x/api.html#express.static) for the possible options. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + staticOptions: { + redirect: false + } + } +}; +``` + +T> This only works when using [`devServer.contentBase`](#devserver-contentbase) as a `string`. + + +## `devServer.stats` 🔑 + +`string: 'none' | 'errors-only' | 'minimal' | 'normal' | 'verbose'` `object` + +This option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you want some bundle information, but not all of it. + +To show only errors in your bundle: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + stats: 'errors-only' + } +}; +``` + +For more information, see the [__stats documentation__](/configuration/stats/). + +T> This option has no effect when used with `quiet` or `noInfo`. + + +## `devServer.stdin` - CLI only + +`boolean` + +This option closes the server when stdin ends. + +```bash +webpack-dev-server --stdin +``` + + +## `devServer.useLocalIp` + +`boolean` + +This option lets the browser open with your local IP. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + useLocalIp: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --useLocalIp +``` + + +## `devServer.watchContentBase` + +`boolean` + +Tell dev-server to watch the files served by the [`devServer.contentBase`](#devserver-contentbase) option. It is disabled by default. When enabled, file changes will trigger a full page reload. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + watchContentBase: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --watch-content-base +``` + + +## `devServer.watchOptions` 🔑 + +`object` + +Control options related to watching the files. + +webpack uses the file system to get notified of file changes. In some cases this does not work. For example, when using Network File System (NFS). [Vagrant](https://www.vagrantup.com/) also has a lot of problems with this. In these cases, use polling: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + watchOptions: { + poll: true + } + } +}; +``` + +If this is too heavy on the file system, you can change this to an integer to set the interval in milliseconds. + +See [WatchOptions](/configuration/watch/) for more options. + + +# Devtool + +This option controls if and how source maps are generated. + +Use the [`SourceMapDevToolPlugin`](/plugins/source-map-dev-tool-plugin) for a more fine grained configuration. See the [`source-map-loader`](/loaders/source-map-loader) to deal with existing source maps. + + +## `devtool` + +`string` `false` + +Choose a style of [source mapping](http://blog.teamtreehouse.com/introduction-source-maps) to enhance the debugging process. These values can affect build and rebuild speed dramatically. + +T> The webpack repository contains an [example showing the effect of all `devtool` variants](https://github.com/webpack/webpack/tree/master/examples/source-map). Those examples will likely help you to understand the differences. + +T> Instead of using the `devtool` option you can also use `SourceMapDevToolPlugin`/`EvalSourceMapDevToolPlugin` directly as it has more options. Never use both the `devtool` option and plugin together. The `devtool` option adds the plugin internally so you would end up with the plugin applied twice. + +devtool | build | rebuild | production | quality +------------------------------ | ----- | ------- | ---------- | ----------------------------- +(none) | +++ | +++ | yes | bundled code +eval | +++ | +++ | no | generated code +cheap-eval-source-map | + | ++ | no | transformed code (lines only) +cheap-module-eval-source-map | o | ++ | no | original source (lines only) +eval-source-map | -- | + | no | original source +cheap-source-map | + | o | yes | transformed code (lines only) +cheap-module-source-map | o | - | yes | original source (lines only) +inline-cheap-source-map | + | o | no | transformed code (lines only) +inline-cheap-module-source-map | o | - | no | original source (lines only) +source-map | -- | -- | yes | original source +inline-source-map | -- | -- | no | original source +hidden-source-map | -- | -- | yes | original source +nosources-source-map | -- | -- | yes | without source content + +T> `+++` super fast, `++` fast, `+` pretty fast, `o` medium, `-` pretty slow, `--` slow + +Some of these values are suited for development and some for production. For development you typically want fast Source Maps at the cost of bundle size, but for production you want separate Source Maps that are accurate and support minimizing. + +W> There are some issues with Source Maps in Chrome. [We need your help!](https://github.com/webpack/webpack/issues/3165). + +T> See [`output.sourceMapFilename`](/configuration/output#output-sourcemapfilename) to customize the filenames of generated Source Maps. + + +### Qualities + +`bundled code` - You see all generated code as a big blob of code. You don't see modules separated from each other. + +`generated code` - You see each module separated from each other, annotated with module names. You see the code generated by webpack. Example: Instead of `import {test} from "module"; test();` you see something like `var module__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); module__WEBPACK_IMPORTED_MODULE_1__.a();`. + +`transformed code` - You see each module separated from each other, annotated with module names. You see the code before webpack transforms it, but after Loaders transpile it. Example: Instead of `import {test} from "module"; class A extends test {}` you see something like `import {test} from "module"; var A = function(_test) { ... }(test);` + +`original source` - You see each module separated from each other, annotated with module names. You see the code before transpilation, as you authored it. This depends on Loader support. + +`without source content` - Contents for the sources are not included in the Source Maps. Browsers usually try to load the source from the webserver or filesystem. You have to make sure to set [`output.devtoolModuleFilenameTemplate`](/configuration/output/#output-devtoolmodulefilenametemplate) correctly to match source urls. + +`(lines only)` - Source Maps are simplified to a single mapping per line. This usually means a single mapping per statement (assuming you author is this way). This prevents you from debugging execution on statement level and from settings breakpoints on columns of a line. Combining with minimizing is not possible as minimizers usually only emit a single line. + + +### Development + +The following options are ideal for development: + +`eval` - Each module is executed with `eval()` and `//@ sourceURL`. This is pretty fast. The main disadvantage is that it doesn't display line numbers correctly since it gets mapped to transpiled code instead of the original code (No Source Maps from Loaders). + +`eval-source-map` - Each module is executed with `eval()` and a SourceMap is added as a DataUrl to the `eval()`. Initially it is slow, but it provides fast rebuild speed and yields real files. Line numbers are correctly mapped since it gets mapped to the original code. It yields the best quality SourceMaps for development. + +`cheap-eval-source-map` - Similar to `eval-source-map`, each module is executed with `eval()`. It is "cheap" because it doesn't have column mappings, it only maps line numbers. It ignores SourceMaps from Loaders and only display transpiled code similar to the `eval` devtool. + +`cheap-module-eval-source-map` - Similar to `cheap-eval-source-map`, however, in this case Source Maps from Loaders are processed for better results. However Loader Source Maps are simplified to a single mapping per line. + +### Special cases + +The following options are not ideal for development nor production. They are needed for some special cases, i. e. for some 3rd party tools. + +`inline-source-map` - A SourceMap is added as a DataUrl to the bundle. + +`cheap-source-map` - A SourceMap without column-mappings ignoring loader Source Maps. + +`inline-cheap-source-map` - Similar to `cheap-source-map` but SourceMap is added as a DataUrl to the bundle. + +`cheap-module-source-map` - A SourceMap without column-mappings that simplifies loader Source Maps to a single mapping per line. + +`inline-cheap-module-source-map` - Similar to `cheap-module-source-map` but SourceMap is added as a DataUrl to the bundle. + + +### Production + +These options are typically used in production: + +`(none)` (Omit the `devtool` option) - No SourceMap is emitted. This is a good option to start with. + +`source-map` - A full SourceMap is emitted as a separate file. It adds a reference comment to the bundle so development tools know where to find it. + +W> You should configure your server to disallow access to the Source Map file for normal users! + +`hidden-source-map` - Same as `source-map`, but doesn't add a reference comment to the bundle. Useful if you only want SourceMaps to map error stack traces from error reports, but don't want to expose your SourceMap for the browser development tools. + +W> You should not deploy the Source Map file to the webserver. Instead only use it for error report tooling. + +`nosources-source-map` - A SourceMap is created without the `sourcesContent` in it. It can be used to map stack traces on the client without exposing all of the source code. You can deploy the Source Map file to the webserver. + +W> It still exposes filenames and structure for decompiling, but it doesn't expose the original code. + +T> When using the `terser-webpack-plugin` you must provide the `sourceMap: true` option to enable SourceMap support. + + +# Target + +webpack can compile for multiple environments or _targets_. To understand what a `target` is in detail, read through [the targets concept page](/concepts/targets/). + +## `target` + +`string | function (compiler)` + +Instructs webpack to target a specific environment. + + +### `string` + +The following string values are supported via [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js): + +Option | Description +--------------------- | ----------------------- +`async-node` | Compile for usage in a Node.js-like environment (uses `fs` and `vm` to load chunks asynchronously) +`electron-main` | Compile for [Electron](https://electronjs.org/) for main process. +`electron-renderer` | Compile for [Electron](https://electronjs.org/) for renderer process, providing a target using `JsonpTemplatePlugin`, `FunctionModulePlugin` for browser environments and `NodeTargetPlugin` and `ExternalsPlugin` for CommonJS and Electron built-in modules. +`node` | Compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks) +`node-webkit` | Compile for usage in WebKit and uses JSONP for chunk loading. Allows importing of built-in Node.js modules and [`nw.gui`](http://docs.nwjs.io/en/latest/) (experimental) +`web` | Compile for usage in a browser-like environment __(default)__ +`webworker` | Compile as WebWorker + +For example, when the `target` is set to `"electron-main"`, webpack includes multiple electron specific variables. For more information on which templates and externals are used, you can refer to webpack's [source code](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js#L148-L183). + + +### `function` + +If a function is passed, then it will be called with the compiler as a parameter. Set it to a function if none of the predefined targets from the list above meet your needs. + +For example, if you don't want any of the plugins they applied: + +```js +const options = { + target: () => undefined +}; +``` + +Or you can apply specific plugins you want: + +```js +const webpack = require('webpack'); + +const options = { + target: (compiler) => { + compiler.apply( + new webpack.JsonpTemplatePlugin(options.output), + new webpack.LoaderTargetPlugin('web') + ); + } +}; +``` + + +# Watch and WatchOptions + +webpack can watch files and recompile whenever they change. This page explains how to enable this and a couple of tweaks you can make if watching does not work properly for you. + + +## `watch` + +`boolean` + +Turn on watch mode. This means that after the initial build, webpack will continue to watch for changes in any of the resolved files. Watch mode is turned off by default: + +```js +module.exports = { + //... + watch: false +}; +``` + +T> In webpack-dev-server and webpack-dev-middleware watch mode is enabled by default. + + +## `watchOptions` + +`object` + +A set of options used to customize watch mode: + +```js +module.exports = { + //... + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + } +}; +``` + + +## `watchOptions.aggregateTimeout` + +`number` + +Add a delay before rebuilding once the first file changed. This allows webpack to aggregate any other changes made during this time period into one rebuild. Pass a value in milliseconds: + +```js +module.exports = { + //... + watchOptions: { + aggregateTimeout: 300 // The default + } +}; +``` + + +## `watchOptions.ignored` + +For some systems, watching many file systems can result in a lot of CPU or memory usage. It is possible to exclude a huge folder like `node_modules`: + +```js +module.exports = { + //... + watchOptions: { + ignored: /node_modules/ + } +}; +``` + +It is also possible to have and use multiple [anymatch](https://github.com/micromatch/anymatch) patterns: + +```js +module.exports = { + //... + watchOptions: { + ignored: ['files/**/*.js', 'node_modules'] + } +}; +``` + +T> If you use `require.context`, webpack will watch your entire directory. You will need to ignore files and/or directories so that unwanted changes will not trigger a rebuild. + + +## `watchOptions.poll` + +`boolean` `number` + +Turn on [polling](https://whatis.techtarget.com/definition/polling) by passing `true`, or specifying a poll interval in milliseconds: + +```js +module.exports = { + //... + watchOptions: { + poll: 1000 // Check for changes every second + } +}; +``` + +T> If watching does not work for you, try out this option. Watching does not work with NFS and machines in VirtualBox. + + +## `info-verbosity` + +`string`: `none` `info` `verbose` + +Controls verbosity of the lifecycle messaging, e.g. the `Started watching files...` log. Setting `info-verbosity` to `verbose` will also message to console at the beginning and the end of incremental build. `info-verbosity` is set to `info` by default. + +```bash +webpack --watch --info-verbosity verbose +``` + + +## Troubleshooting + +If you are experiencing any issues, please see the following notes. There are a variety of reasons why webpack might miss a file change. + +### Changes Seen But Not Processed + +Verify that webpack is not being notified of changes by running webpack with the --progress flag. If progress shows on save but no files are outputted, it is likely a configuration issue, not a file watching issue. + +```bash +webpack --watch --progress +``` + +### Not Enough Watchers + +Verify that you have enough available watchers in your system. If this value is too low, the file watcher in Webpack won't recognize the changes: + +```bash +cat /proc/sys/fs/inotify/max_user_watches +``` + +Arch users, add `fs.inotify.max_user_watches=524288` to `/etc/sysctl.d/99-sysctl.conf` and then execute `sysctl --system`. Ubuntu users (and possibly others), execute: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`. + +### macOS fsevents Bug + +On macOS, folders can get corrupted in certain scenarios. See [this article](https://github.com/livereload/livereload-site/blob/master/livereload.com/_articles/troubleshooting/os-x-fsevents-bug-may-prevent-monitoring-of-certain-folders.md). + +### Windows Paths + +Because webpack expects absolute paths for many config options such as `__dirname + "/app/folder"` the Windows `\` path separator can break some functionality. + +Use the correct separators. I.e. `path.resolve(__dirname, "app/folder")` or `path.join(__dirname, "app", "folder")`. + +### Vim + +On some machines Vim is preconfigured with the [backupcopy option](http://vimdoc.sourceforge.net/htmldoc/options.html#'backupcopy') set to `auto`. This could potentially cause problems with the system's file watching mechanism. Switching this option to `yes` will make sure a copy of the file is made and the original one overwritten on save. + +`:set backupcopy=yes` + +### Saving in WebStorm + +When using the JetBrains WebStorm IDE, you may find that saving changed files does not trigger the watcher as you might expect. Try disabling the `safe write` option in the settings, which determines whether files are saved to a temporary location first before the originals are overwritten: uncheck `File > Settings... > System Settings > Use "safe write" (save changes to a temporary file first)`. + + +# Externals + +The `externals` configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment. This feature is typically most useful to __library developers__, however there are a variety of applications for it. + +T> __consumer__ here is any end user application that includes the library that you have bundled using webpack. + + +## `externals` + +`string` `object` `function` `regex` + +__Prevent bundling__ of certain `import`ed packages and instead retrieve these _external dependencies_ at runtime. + +For example, to include [jQuery](https://jquery.com/) from a CDN instead of bundling it: + +__index.html__ + +``` html +<script + src="https://code.jquery.com/jquery-3.1.0.js" + integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" + crossorigin="anonymous"> +</script> +``` + +__webpack.config.js__ + +```javascript +module.exports = { + //... + externals: { + jquery: 'jQuery' + } +}; +``` + +This leaves any dependent modules unchanged, i.e. the code shown below will still work: + +```javascript +import $ from 'jquery'; + +$('.my-element').animate(/* ... */); +``` + +The bundle with external dependencies can be used in various module contexts, such as [CommonJS, AMD, global and ES2015 modules](/concepts/modules). The external library may be available in any of these forms: + +- __root__: The library should be available as a global variable (e.g. via a script tag). +- __commonjs__: The library should be available as a CommonJS module. +- __commonjs2__: Similar to the above but where the export is `module.exports.default`. +- __amd__: Similar to `commonjs` but using AMD module system. + +The following syntaxes are accepted... + + +### string + +See the example above. The property name `jquery` indicates that the module `jquery` in `import $ from 'jquery'` should be excluded. In order to replace this module, the value `jQuery` will be used to retrieve a global `jQuery` variable. In other words, when a string is provided it will be treated as `root` (defined above and below). + + +### array + +```javascript +module.exports = { + //... + externals: { + subtract: ['./math', 'subtract'] + } +}; +``` + +`subtract: ['./math', 'subtract']` converts to a parent child construct, where `./math` is the parent module and your bundle only requires the subset under `subtract` variable. + + +### object + +W> An object with `{ root, amd, commonjs, ... }` is only allowed for [`libraryTarget: 'umd'`](/configuration/output/#output-librarytarget). It's not allowed for other library targets. + +```javascript +module.exports = { + //... + externals : { + react: 'react' + }, + + // or + + externals : { + lodash : { + commonjs: 'lodash', + amd: 'lodash', + root: '_' // indicates global variable + } + }, + + // or + + externals : { + subtract : { + root: ['math', 'subtract'] + } + } +}; +``` + +This syntax is used to describe all the possible ways that an external library can be available. `lodash` here is available as `lodash` under AMD and CommonJS module systems but available as `_` in a global variable form. `subtract` here is available via the property `subtract` under the global `math` object (e.g. `window['math']['subtract']`). + + +### function + +It might be useful to define your own function to control the behavior of what you want to externalize from webpack. [webpack-node-externals](https://www.npmjs.com/package/webpack-node-externals), for example, excludes all modules from the `node_modules` directory and provides some options to, for example, whitelist packages. + +It basically comes down to this: + +```javascript +module.exports = { + //... + externals: [ + function(context, request, callback) { + if (/^yourregex$/.test(request)){ + return callback(null, 'commonjs ' + request); + } + callback(); + } + ] +}; +``` + +The `'commonjs ' + request` defines the type of module that needs to be externalized. + + +### regex + +Every dependency that matches the given regular expression will be excluded from the output bundles. + +```javascript +module.exports = { + //... + externals: /^(jquery|\$)$/i +}; +``` + +In this case any dependency named `jQuery`, capitalized or not, or `$` would be externalized. + +### Combining syntaxes + +Sometimes you may want to use a combination of the above syntaxes. This can be done in the following manner: + +```javascript +module.exports = { + //... + externals: [ + { + // String + react: 'react', + // Object + lodash : { + commonjs: 'lodash', + amd: 'lodash', + root: '_' // indicates global variable + }, + // Array + subtract: ['./math', 'subtract'] + }, + // Function + function(context, request, callback) { + if (/^yourregex$/.test(request)){ + return callback(null, 'commonjs ' + request); + } + callback(); + }, + // Regex + /^(jquery|\$)$/i + ] +}; +``` + +For more information on how to use this configuration, please refer to the article on [how to author a library](/guides/author-libraries). + + +# Node + +These options configure whether to polyfill or mock certain [Node.js globals](https://nodejs.org/docs/latest/api/globals.html) and modules. This allows code originally written for the Node.js environment to run in other environments like the browser. + +This feature is provided by webpack's internal [`NodeStuffPlugin`](https://github.com/webpack/webpack/blob/master/lib/NodeStuffPlugin.js) plugin. If the target is "web" (default) or "webworker", the [`NodeSourcePlugin`](https://github.com/webpack/webpack/blob/master/lib/node/NodeSourcePlugin.js) plugin is also activated. + + +## `node` + +`object` + +This is an object where each property is the name of a Node global or module and each value may be one of the following... + +- `true`: Provide a polyfill. +- `"mock"`: Provide a mock that implements the expected interface but has little or no functionality. +- `"empty"`: Provide an empty object. +- `false`: Provide nothing. Code that expects this object may crash with a `ReferenceError`. Code that attempts to import the module using `require('modulename')` may trigger a `Cannot find module "modulename"` error. + +W> Not every Node global supports all four options. The compiler will throw an error for property-value combinations that aren't supported (e.g. `process: 'empty'`). See the sections below for more details. + +These are the defaults: + +```js +module.exports = { + //... + node: { + console: false, + global: true, + process: true, + __filename: 'mock', + __dirname: 'mock', + Buffer: true, + setImmediate: true + + // See "Other node core libraries" for additional options. + } +}; +``` + +Since webpack 3.0.0, the `node` option may be set to `false` to completely turn off the `NodeStuffPlugin` and `NodeSourcePlugin` plugins. + + +## `node.console` + +`boolean | "mock"` + +Default: `false` + +The browser provides a `console` object with a very similar interface to the Node.js `console`, so a polyfill is generally not needed. + + +## `node.process` + +`boolean | "mock"` + +Default: `true` + + +## `node.global` + +`boolean` + +Default: `true` + +See [the source](https://github.com/webpack/webpack/blob/master/buildin/global.js) for the exact behavior of this object. + + +## `node.__filename` + +`boolean | "mock"` + +Default: `"mock"` + +Options: + +- `true`: The filename of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). +- `false`: The regular Node.js `__filename` behavior. The filename of the __output__ file when run in a Node.js environment. +- `"mock"`: The fixed value `"index.js"`. + + +## `node.__dirname` + +`boolean | "mock"` + +Default: `"mock"` + +Options: + +- `true`: The dirname of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). +- `false`: The regular Node.js `__dirname` behavior. The dirname of the __output__ file when run in a Node.js environment. +- `"mock"`: The fixed value `"/"`. + + +## `node.Buffer` + +`boolean | "mock"` + +Default: `true` + + +## `node.setImmediate` + +`boolean | "mock" | "empty"` + +Default: `true` + + +## Other node core libraries + +`boolean | "mock" | "empty"` + +W> This option is only activated (via `NodeSourcePlugin`) when the target is unspecified, "web" or "webworker". + +Polyfills for Node.js core libraries from [`node-libs-browser`](https://github.com/webpack/node-libs-browser) are used if available, when the `NodeSourcePlugin` plugin is enabled. See the list of [Node.js core libraries and their polyfills](https://github.com/webpack/node-libs-browser#readme). + +By default, webpack will polyfill each library if there is a known polyfill or do nothing if there is not one. In the latter case, webpack will behave as if the module name was configured with the `false` value. + +T> To import a built-in module, use [`__non_webpack_require__`](/api/module-variables/#__non_webpack_require__-webpack-specific-), i.e. `__non_webpack_require__('modulename')` instead of `require('modulename')`. + +Example: + +```js +module.exports = { + //... + node: { + dns: 'mock', + fs: 'empty', + path: true, + url: false + } +}; +``` + + +# Performance + +These options allows you to control how webpack notifies you of assets and entry points that exceed a specific file limit. +This feature was inspired by the idea of [webpack Performance Budgets](https://github.com/webpack/webpack/issues/3216). + +## `performance` + +`object` + +Configure how performance hints are shown. For example if you have an asset that is over 250kb, webpack will emit a warning notifying you of this. + + +## `performance.hints` + +`false | "error" | "warning"` + +Turns hints on/off. In addition, tells webpack to throw either an error or a warning when hints are found. This property is set to `"warning"` by default. + +Given an asset is created that is over 250kb: + +```js +module.exports = { + //... + performance: { + hints: false + } +}; +``` + +No hint warnings or errors are shown. + +```js +module.exports = { + //... + performance: { + hints: 'warning' + } +}; +``` + +A warning will be displayed notifying you of a large asset. We recommend something like this for development environments. + +```js +module.exports = { + //... + performance: { + hints: 'error' + } +}; +``` + +An error will be displayed notifying you of a large asset. We recommend using `hints: "error"` during production builds to help prevent deploying production bundles that are too large, impacting webpage performance. + +## `performance.maxEntrypointSize` + +`int` + +An entry point represents all assets that would be utilized during initial load time for a specific entry. This option controls when webpack should emit performance hints based on the maximum entry point size. The default value is `250000` (bytes). + +```js +module.exports = { + //... + performance: { + maxEntrypointSize: 400000 + } +}; +``` + +## `performance.maxAssetSize` + +`int` + +An asset is any emitted file from webpack. This option controls when webpack emits a performance hint based on individual asset size. The default value is `250000` (bytes). + + +```js +module.exports = { + //... + performance: { + maxAssetSize: 100000 + } +}; +``` + +## `performance.assetFilter` + +`Function` + +This property allows webpack to control what files are used to calculate performance hints. The default function is seen below: + +```js +function assetFilter(assetFilename) { + return !(/\.map$/.test(assetFilename)); +} +``` + +You can override this property by passing your own function in: + +```js +module.exports = { + //... + performance: { + assetFilter: function(assetFilename) { + return assetFilename.endsWith('.js'); + } + } +}; +``` + +The example above will only give you performance hints based on `.js` files. + + +# Stats + +The `stats` option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you don't want to use `quiet` or `noInfo` because you want some bundle information, but not all of it. + +T> For webpack-dev-server, this property needs to be in the `devServer` object. + +W> This option does not have any effect when using the Node.js API. + +## `stats` + +`object` `string` + +There are some presets available to use as a shortcut. Use them like this: + +```js +module.exports = { + //... + stats: 'errors-only' +}; +``` + +| Preset | Alternative | Description | +|--------|-------------|-------------| +| `"errors-only"` | _none_ | Only output when errors happen | +| `"minimal"` | _none_ | Only output when errors or new compilation happen | +| `"none"` | `false` | Output nothing | +| `"normal"` | `true` | Standard output | +| `"verbose"` | _none_ | Output everything | + +For more granular control, it is possible to specify exactly what information you want. Please note that all of the options in this object are optional. + +<!-- eslint-skip --> + +```js +module.exports = { + //... + stats: { + // fallback value for stats options when an option is not defined (has precedence over local webpack defaults) + all: undefined, + + // Add asset Information + assets: true, + + // Sort assets by a field + // You can reverse the sort with `!field`. + // Some possible values: 'id' (default), 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + assetsSort: "field", + + // Add build date and time information + builtAt: true, + + // Add information about cached (not built) modules + cached: true, + + // Show cached assets (setting this to `false` only shows emitted files) + cachedAssets: true, + + // Add children information + children: true, + + // Add chunk information (setting this to `false` allows for a less verbose output) + chunks: true, + + // Add namedChunkGroups information + chunkGroups: true, + + // Add built modules information to chunk information + chunkModules: true, + + // Add the origins of chunks and chunk merging info + chunkOrigins: true, + + // Sort the chunks by a field + // You can reverse the sort with `!field`. Default is `id`. + // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + chunksSort: "field", + + // Context directory for request shortening + context: "../src/", + + // `webpack --colors` equivalent + colors: false, + + // Display the distance from the entry point for each module + depth: false, + + // Display the entry points with the corresponding bundles + entrypoints: false, + + // Add --env information + env: false, + + // Add errors + errors: true, + + // Add details to errors (like resolving log) + errorDetails: true, + + // Exclude assets from being displayed in stats + // This can be done with a String, a RegExp, a Function getting the assets name + // and returning a boolean or an Array of the above. + excludeAssets: "filter" | /filter/ | (assetName) => true | false | + ["filter"] | [/filter/] | [(assetName) => true|false], + + // Exclude modules from being displayed in stats + // This can be done with a String, a RegExp, a Function getting the modules source + // and returning a boolean or an Array of the above. + excludeModules: "filter" | /filter/ | (moduleSource) => true | false | + ["filter"] | [/filter/] | [(moduleSource) => true|false], + + // See excludeModules + exclude: "filter" | /filter/ | (moduleSource) => true | false | + ["filter"] | [/filter/] | [(moduleSource) => true|false], + + // Add the hash of the compilation + hash: true, + + // Set the maximum number of modules to be shown + maxModules: 15, + + // Add built modules information + modules: true, + + // Sort the modules by a field + // You can reverse the sort with `!field`. Default is `id`. + // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + modulesSort: "field", + + // Show dependencies and origin of warnings/errors (since webpack 2.5.0) + moduleTrace: true, + + // Show performance hint when file size exceeds `performance.maxAssetSize` + performance: true, + + // Show the exports of the modules + providedExports: false, + + // Add public path information + publicPath: true, + + // Add information about the reasons why modules are included + reasons: true, + + // Add the source code of modules + source: false, + + // Add timing information + timings: true, + + // Show which exports of a module are used + usedExports: false, + + // Add webpack version information + version: true, + + // Add warnings + warnings: true, + + // Filter warnings to be shown (since webpack 2.4.0), + // can be a String, Regexp, a function getting the warning and returning a boolean + // or an Array of a combination of the above. First match wins. + warningsFilter: "filter" | /filter/ | ["filter", /filter/] | (warning) => true|false + } +} +``` + +If you want to use one of the pre-defined behaviours e.g. `'minimal'` but still override one or more of the rules, see [the source code](https://github.com/webpack/webpack/blob/master/lib/Stats.js#L1394-L1401). You would want to copy the configuration options from `case 'minimal': ...` and add your additional rules while providing an object to `stats`. + +__webpack.config.js__ + +```javascript +module.exports = { + //.. + stats: { + // copied from `'minimal'` + all: false, + modules: true, + maxModules: 0, + errors: true, + warnings: true, + // our additional options + moduleTrace: true, + errorDetails: true + } +}; +``` + +### Sorting fields + +For `assetsSort`, `chunksSort` and `moduleSort` there are several possible fields that you can sort items by: + +- `id` is the item's id; +- `name` - a item's name that was assigned to it upon importing; +- `size` - a size of item in bytes; +- `chunks` - what chunks the item originates from (for example, if there are multiple subchunks for one chunk - the subchunks will be grouped together according to their main chunk); +- `errors` - amount of errors in items; +- `warnings` - amount of warnings in items; +- `failed` - whether the item has failed compilation; +- `cacheable` - whether the item is cacheable; +- `built` - whether the asset has been built; +- `prefetched` - whether the asset will be prefetched; +- `optional` - whether the asset is optional; +- `identifier` - identifier of the item; +- `index` - item's processing index; +- `index2` +- `profile` +- `issuer` - an identifier of the issuer; +- `issuerId` - an id of the issuer; +- `issuerName` - a name of the issuer; +- `issuerPath` - a full issuer object. There's no real need to sort by this field; + + +# Other Options + + +These are the remaining configuration options supported by webpack. + +W> Help Wanted: This page is still a work in progress. If you are familiar with any of the options for which the description or examples are incomplete, please create an issue and submit a PR at the [docs repo](https://github.com/webpack/webpack.js.org)! + + +## `amd` + +`object` + +Set the value of `require.amd` or `define.amd`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + amd: { + jQuery: true + } +}; +``` + +Certain popular modules written for AMD, most notably jQuery versions 1.7.0 to 1.9.1, will only register as an AMD module if the loader indicates it has taken [special allowances](https://github.com/amdjs/amdjs-api/wiki/jQuery-and-AMD) for multiple versions being included on a page. + +The allowances were the ability to restrict registrations to a specific version or to support different sandboxes with different defined modules. + +This option allows you to set the key your module looks for to a truthy value. +As it happens, the AMD support in webpack ignores the defined name anyways. + + +## `bail` + +`boolean` + +Fail out on the first error instead of tolerating it. By default webpack will log these errors in red in the terminal, as well as the browser console when using HMR, but continue bundling. To enable it: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + bail: true +}; +``` + +This will force webpack to exit its bundling process. + + +## `cache` + +`boolean` `object` + +Cache the generated webpack modules and chunks to improve build speed. Caching is enabled by default while in watch mode. To disable caching simply pass: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + cache: false +}; +``` + +If an object is passed, webpack will use this object for caching. Keeping a reference to this object will allow one to share the same cache between compiler calls: + +__webpack.config.js__ + +```javascript +let SharedCache = {}; + +module.exports = { + //... + cache: SharedCache +}; +``` + +W> Don't share the cache between calls with different options. + +?> Elaborate on the warning and example - calls with different configuration options? + + +## `loader` + +`object` + +Expose custom values into the loader context. + +?> Add an example... + + +## `parallelism` + +`number` + +Limit the number of parallel processed modules. Can be used to fine tune performance or to get more reliable profiling results. + + +## `profile` + +`boolean` + +Capture a "profile" of the application, including statistics and hints, which can then be dissected using the [Analyze](https://webpack.github.io/analyse/) tool. + +T> Use the [StatsPlugin](https://www.npmjs.com/package/stats-webpack-plugin) for more control over the generated profile. + +T> Combine with `parallelism: 1` for better results. + + +## `recordsPath` + +`string` + +Use this option to generate a JSON file containing webpack "records" -- pieces of data used to store module identifiers across multiple builds. You can use this file to track how modules change between builds. To generate one, simply specify a location: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + recordsPath: path.join(__dirname, 'records.json') +}; +``` + +Records are particularly useful if you have a complex setup that leverages [Code Splitting](/guides/code-splitting). The data can be used to ensure the split bundles are achieving the [caching](/guides/caching) behavior you need. + +T> Note that although this file is generated by the compiler, you may still want to track it in source control to keep a history of how it has changed over time. + +W> Setting `recordsPath` will essentially set `recordsInputPath` and `recordsOutputPath` to the same location. This is usually all that's necessary unless you decide to change the name of the file containing the records. See below for an example. + + +## `recordsInputPath` + +`string` + +Specify the file from which to read the last set of records. This can be used to rename a records file. See the example below. + + +## `recordsOutputPath` + +`string` + +Specify where the records should be written. The following example shows how you might use this option in combination with `recordsInputPath` to rename a records file: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + recordsInputPath: path.join(__dirname, 'records.json'), + recordsOutputPath: path.join(__dirname, 'newRecords.json') +}; +``` + + +## `name` + +`string` + +Name of the configuration. Used when loading multiple configurations. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + name: 'admin-app' +}; +``` diff --git a/src/content/contribute/_contribute_all.md b/src/content/contribute/_contribute_all.md new file mode 100644 index 000000000000..beab316a12a7 --- /dev/null +++ b/src/content/contribute/_contribute_all.md @@ -0,0 +1,979 @@ + + +# Contribute + +The people who contribute to webpack do so for the love of open source, our users and ecosystem, and most importantly, pushing the web forward together. Because of our [Open Collective](https://opencollective.com/webpack) model for funding and transparency, we are able to funnel support and funds through contributors, dependent projects, and the contributor and core teams. To make a donation, simply click the button below... + +<div align="center"> + <a href="https://opencollective.com/webpack/donate" target="_blank"> + <img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" width=300 /> + </a> +</div> + +But what is the return on the investment? + + +## Developers + +The biggest core feature we'd like to provide is enjoyable development experience. Developers like you can help by contributing to rich and vibrant documentation, issuing pull requests to help us cover niche use cases, and to help sustain what you love about webpack. + +### How Can I Help? + +Anybody can help by doing any of the following: + +- Ask your employer to use webpack in projects. +- Help us write and maintain the content on this site (see the [writer's guide](/writers-guide)). +- Contribute to the [core repository](https://github.com/webpack/webpack). +- Become a backer or sponsor on [open collective](https://opencollective.com/webpack#support). + +### Encouraging Employers + +You can ask your employer to improve your workflow by leveraging webpack: an all-in-one tool for fonts, images and image optimization, and json. Explain to them how webpack will attempt to bundle your code and assets the best it can for the smallest file size, leading to speedier sites and applications. + +### Your Contributions + +Contributing to webpack is not contributing to an exclusive club. You as a developer are contributing to the overall health of downstream projects. Hundreds, if not thousands, of projects depend on webpack and contributing will make the ecosystem better for all users. + +The remainder of this section of the site is dedicated to developers such as yourself who would like to become a part of our ever-growing community: + +- [Writing a Loader](./writing-a-loader) +- [Writing a Plugin](./writing-a-plugin) +- [Plugin Patterns](./plugin-patterns) +- [Release Process](./release-process) + + +## Executives + +CTO's, VPs, and owners can help too! + +<!-- add slides here regarding monetary value/dev time/tooling --> + +webpack is an all-in-one tool for bundling your code. It can handle fonts, images, data and more with the help of community-driven plugins and loaders. Having all of your assets be handled by one tool is immensely helpful, as you or your team can spend less time making sure a machine with many moving parts is working correctly and more time building your product. + +### Sponsorship + +Aside from monetary assistance, companies can support webpack by: + +- Providing developers that are not actively working on a project. +- Contributing computing power for improved CI and regression testing. + +You can also encourage your developers to contribute to the ecosystem by open-sourcing webpack loaders, plugins and other utilities. And, as mentioned above, we would greatly appreciate any help increasing our CI/CD infrastructure. + +### Anyone Else + +To anyone else who is interested in helping our mission -- e.g. venture capitalists, government entities, digital agencies, etc. -- we would love for you to work with us, one of the top npm packages, to improve your product! Please don't hesitate to reach out with questions. + +<!-- add slides here --> + + +# Writer's Guide + +The following sections contain all you need to know about editing and formatting the content within this site. Make sure to do some research before starting your edits or additions. Sometimes the toughest part is finding where the content should live and determining whether or not it already exists. + + +## Process + +1. Check related issue if an article links to one. +2. Hit `edit` and expand on the structure. +3. PR changes. + + +## YAML Frontmatter + +Each article contains a small section at the top written in [YAML Frontmatter](https://jekyllrb.com/docs/frontmatter/): + +``` yaml +--- +title: My Article +group: My Sub-Section +sort: 3 +contributors: + - [github username] +related: + - title: Title of Related Article + url: [url of related article] +--- +``` + +Let's break these down: + +- `title`: The name of the article. +- `group`: The name of the sub-section +- `sort`: The order of the article within its section (or) sub-section if it is present. +- `contributors`: A list of GitHub usernames who have contributed to this article. +- `related`: Any related reading or useful examples. + +Note that `related` will generate a __Further Reading__ section at the bottom of the page and `contributors` will yield a __Contributors__ section below it. If you edit an article and would like recognition, don't hesitate to add your GitHub username to the `contributors` list. + + +## Article Structure + +1. Brief Introduction - a paragraph or two so you get the basic idea about the what and why. +2. Outline Remaining Content – how the content will be presented. +3. Main Content - tell what you promised to tell. +4. Conclusion - tell what you told and recap the main points. + + +## Typesetting + +- webpack should always be written in lower-case letters. Even at the beginning of a sentence. ([source](https://github.com/webpack/media#name)) +- loaders are enclosed in backticks and [kebab-cased](https://en.wikipedia.org/w/index.php?title=Kebab_case): `css-loader`, `ts-loader`, … +- plugins are enclosed in backticks and [camel-cased](https://en.wikipedia.org/wiki/Camel_case): `BannerPlugin`, `NpmInstallWebpackPlugin`, … +- Use "webpack 2" to refer to a specific webpack version (~~"webpack v2"~~) +- Use ES5; ES2015, ES2016, … to refer to the ECMAScript standards (~~ES6~~, ~~ES7~~) + + +## Formatting + +### Code + +__Syntax: \`\`\`javascript … \`\`\`__ + +```javascript +function foo () { + return 'bar'; +} + +foo(); +``` + +### Lists + +- Boo +- Foo +- Zoo + +Lists should be ordered alphabetically. + +### Tables + +Parameter | Explanation | Input Type | Default Value +----------- | ------------------------------------------------ | ---------- |-------------- +--debug | Switch loaders to debug mode | boolean | false +--devtool | Define source map type for the bundled resources | string | - +--progress | Print compilation progress in percentage | boolean | false + +Tables should also be ordered alphabetically. + +### Configuration Properties + +The [configuration](/configuration) properties should be ordered alphabetically as well: + +- `devServer.compress` +- `devServer.contentBase` +- `devServer.hot` + +### Quotes + +#### Blockquote + +__Syntax: \>__ + +> This is a blockquote. + +#### Tip + +__Syntax: T\>__ + +T> This is a tip. + +__Syntax: W\>__ + +W> This is a warning. + +__Syntax: ?\>__ + +?> This is a todo. + + +# Writing a Loader + +A loader is a node module that exports a function. This function is called when a resource should be transformed by this loader. The given function will have access to the [Loader API](/api/loaders/) using the `this` context provided to it. + + +## Setup + +Before we dig into the different types of loaders, their usage, and examples, let's take a look at the three ways you can develop and test a loader locally. + +To test a single loader, you can simply use `path` to `resolve` a local file within a rule object: + +__webpack.config.js__ + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + use: [ + { + loader: path.resolve('path/to/loader.js'), + options: {/* ... */} + } + ] + } + ] + } +}; +``` + +To test multiple, you can utilize the `resolveLoader.modules` configuration to update where webpack will search for loaders. For example, if you had a local `/loaders` directory in your project: + +__webpack.config.js__ + +```js +module.exports = { + //... + resolveLoader: { + modules: [ + 'node_modules', + path.resolve(__dirname, 'loaders') + ] + } +}; +``` + +Last but not least, if you've already created a separate repository and package for your loader, you could [`npm link`](https://docs.npmjs.com/cli/link) it to the project in which you'd like to test it out. + + +## Simple Usage + +When a single loader is applied to the resource, the loader is called with only one parameter -- a string containing the content of the resource file. + +Synchronous loaders can simply `return` a single value representing the transformed module. In more complex cases, the loader can return any number of values by using the `this.callback(err, values...)` function. Errors are either passed to the `this.callback` function or thrown in a sync loader. + +The loader is expected to give back one or two values. The first value is a resulting JavaScript code as string or buffer. The second optional value is a SourceMap as JavaScript object. + + +## Complex Usage + +When multiple loaders are chained, it is important to remember that they are executed in reverse order -- either right to left or bottom to top depending on array format. + +- The last loader, called first, will be passed the contents of the raw resource. +- The first loader, called last, is expected to return JavaScript and an optional source map. +- The loaders in between will be executed with the result(s) of the previous loader in the chain. + +So, in the following example, the `foo-loader` would be passed the raw resource and the `bar-loader` would receive the output of the `foo-loader` and return the final transformed module and a source map if necessary. + +__webpack.config.js__ + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js/, + use: [ + 'bar-loader', + 'foo-loader' + ] + } + ] + } +}; +``` + + +## Guidelines + +The following guidelines should be followed when writing a loader. They are ordered in terms of importance and some only apply in certain scenarios, read the detailed sections that follow for more information. + +- Keep them __simple__. +- Utilize __chaining__. +- Emit __modular__ output. +- Make sure they're __stateless__. +- Employ __loader utilities__. +- Mark __loader dependencies__. +- Resolve __module dependencies__. +- Extract __common code__. +- Avoid __absolute paths__. +- Use __peer dependencies__. + +### Simple + +Loaders should do only a single task. This not only makes the job of maintaining each loader easier, but also allows them to be chained for usage in more scenarios. + +### Chaining + +Take advantage of the fact that loaders can be chained together. Instead of writing a single loader that tackles five tasks, write five simpler loaders that divide this effort. Isolating them not only keeps each individual loader simple, but may allow for them to be used for something you hadn't thought of originally. + +Take the case of rendering a template file with data specified via loader options or query parameters. It could be written as a single loader that compiles the template from source, executes it and returns a module that exports a string containing the HTML code. However, in accordance with guidelines, a simple `apply-loader` exists that can be chained with other open source loaders: + +- `jade-loader`: Convert template to a module that exports a function. +- `apply-loader`: Executes the function with loader options and returns raw HTML. +- `html-loader`: Accepts HTML and outputs a valid JavaScript module. + +T> The fact that loaders can be chained also means they don't necessarily have to output JavaScript. As long as the next loader in the chain can handle its output, the loader can return any type of module. + +### Modular + +Keep the output modular. Loader generated modules should respect the same design principles as normal modules. + +### Stateless + +Make sure the loader does not retain state between module transformations. Each run should always be independent of other compiled modules as well as previous compilations of the same module. + +### Loader Utilities + +Take advantage of the [`loader-utils`](https://github.com/webpack/loader-utils) package. It provides a variety of useful tools but one of the most common is retrieving the options passed to the loader. Along with `loader-utils`, the [`schema-utils`](https://github.com/webpack-contrib/schema-utils) package should be used for consistent JSON Schema based validation of loader options. Here's a brief example that utilizes both: + +__loader.js__ + +```js +import { getOptions } from 'loader-utils'; +import validateOptions from 'schema-utils'; + +const schema = { + type: 'object', + properties: { + test: { + type: 'string' + } + } +}; + +export default function(source) { + const options = getOptions(this); + + validateOptions(schema, options, 'Example Loader'); + + // Apply some transformations to the source... + + return `export default ${ JSON.stringify(source) }`; +} +``` + +### Loader Dependencies + +If a loader uses external resources (i.e. by reading from filesystem), they __must__ indicate it. This information is used to invalidate cacheable loaders and recompile in watch mode. Here's a brief example of how to accomplish this using the `addDependency` method: + +__loader.js__ + +```js +import path from 'path'; + +export default function(source) { + var callback = this.async(); + var headerPath = path.resolve('header.js'); + + this.addDependency(headerPath); + + fs.readFile(headerPath, 'utf-8', function(err, header) { + if(err) return callback(err); + callback(null, header + '\n' + source); + }); +} +``` + +### Module Dependencies + +Depending on the type of module, there may be a different schema used to specify dependencies. In CSS for example, the `@import` and `url(...)` statements are used. These dependencies should be resolved by the module system. + +This can be done in one of two ways: + +- By transforming them to `require` statements. +- Using the `this.resolve` function to resolve the path. + +The `css-loader` is a good example of the first approach. It transforms dependencies to `require`s, by replacing `@import` statements with a `require` to the other stylesheet and `url(...)` with a `require` to the referenced file. + +In the case of the `less-loader`, it cannot transform each `@import` to a `require` because all `.less` files must be compiled in one pass for variables and mixin tracking. Therefore, the `less-loader` extends the less compiler with custom path resolving logic. It then takes advantage of the second approach, `this.resolve`, to resolve the dependency through webpack. + +T> If the language only accepts relative urls (e.g. `url(file)` always refers to `./file`), you can use the `~` convention to specify references to installed modules (e.g. those in `node_modules`). So, in the case of `url`, that would look something like `url('~some-library/image.jpg')`. + +### Common Code + +Avoid generating common code in every module the loader processes. Instead, create a runtime file in the loader and generate a `require` to that shared module. + +### Absolute Paths + +Don't insert absolute paths into the module code as they break hashing when the root for the project is moved. There's a [`stringifyRequest`](https://github.com/webpack/loader-utils#stringifyrequest) method in `loader-utils` which can be used to convert an absolute path to a relative one. + +### Peer Dependencies + +If the loader you're working on is a simple wrapper around another package, then you should include the package as a `peerDependency`. This approach allows the application's developer to specify the exact version in the `package.json` if desired. + +For instance, the `sass-loader` [specifies `node-sass`](https://github.com/webpack-contrib/sass-loader/blob/master/package.json) as peer dependency like so: + +```json +{ + "peerDependencies": { + "node-sass": "^4.0.0" + } +} +``` + + +## Testing + +So you've written a loader, followed the guidelines above, and have it set up to run locally. What's next? Let's go through a simple unit testing example to ensure our loader is working the way we expect. We'll be using the [Jest](https://facebook.github.io/jest/) framework to do this. We'll also install `babel-jest` and some presets that will allow us to use the `import` / `export` and `async` / `await`. Let's start by installing and saving these as a `devDependencies`: + +``` bash +npm install --save-dev jest babel-jest babel-preset-env +``` + +__.babelrc__ + +```json +{ + "presets": [[ + "env", + { + "targets": { + "node": "4" + } + } + ]] +} +``` + +Our loader will process `.txt` files and simply replace any instance of `[name]` with the `name` option given to the loader. Then it will output a valid JavaScript module containing the text as it's default export: + +__src/loader.js__ + +```js +import { getOptions } from 'loader-utils'; + +export default function loader(source) { + const options = getOptions(this); + + source = source.replace(/\[name\]/g, options.name); + + return `export default ${ JSON.stringify(source) }`; +} +``` + +We'll use this loader to process the following file: + +__test/example.txt__ + +``` text +Hey [name]! +``` + +Pay close attention to this next step as we'll be using the [Node.js API](/api/node) and [`memory-fs`](https://github.com/webpack/memory-fs) to execute webpack. This lets us avoid emitting `output` to disk and will give us access to the `stats` data which we can use to grab our transformed module: + +``` bash +npm install --save-dev webpack memory-fs +``` + +__test/compiler.js__ + +```js +import path from 'path'; +import webpack from 'webpack'; +import memoryfs from 'memory-fs'; + +export default (fixture, options = {}) => { + const compiler = webpack({ + context: __dirname, + entry: `./${fixture}`, + output: { + path: path.resolve(__dirname), + filename: 'bundle.js', + }, + module: { + rules: [{ + test: /\.txt$/, + use: { + loader: path.resolve(__dirname, '../src/loader.js'), + options: { + name: 'Alice' + } + } + }] + } + }); + + compiler.outputFileSystem = new memoryfs(); + + return new Promise((resolve, reject) => { + compiler.run((err, stats) => { + if (err || stats.hasErrors()) reject(err); + + resolve(stats); + }); + }); +}; +``` + +T> In this case, we've inlined our webpack configuration but you can also accept a configuration as a parameter to the exported function. This would allow you to test multiple setups using the same compiler module. + +And now, finally, we can write our test and add an npm script to run it: + +__test/loader.test.js__ + +```js +import compiler from './compiler.js'; + +test('Inserts name and outputs JavaScript', async () => { + const stats = await compiler('example.txt'); + const output = stats.toJson().modules[0].source; + + expect(output).toBe('export default "Hey Alice!\\n"'); +}); +``` + +__package.json__ + +```json +{ + "scripts": { + "test": "jest" + } +} +``` + +With everything in place, we can run it and see if our new loader passes the test: + +``` bash + PASS test/loader.test.js + ✓ Inserts name and outputs JavaScript (229ms) + +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: 1.853s, estimated 2s +Ran all test suites. +``` + +It worked! At this point you should be ready to start developing, testing, and deploying your own loaders. We hope that you'll share your creations with the rest of the community! + + +# Writing a Plugin + +Plugins expose the full potential of the webpack engine to third-party developers. Using staged build callbacks, developers can introduce their own behaviors into the webpack build process. Building plugins is a bit more advanced than building loaders, because you'll need to understand some of the webpack low-level internals to hook into them. Be prepared to read some source code! + +## Creating a Plugin + +A plugin for webpack consists of + +- A named JavaScript function. +- Defines `apply` method in its prototype. +- Specifies an [event hook](/api/compiler-hooks/) to tap into. +- Manipulates webpack internal instance specific data. +- Invokes webpack provided callback after functionality is complete. + +```javascript +// A JavaScript class. +class MyExampleWebpackPlugin { + // Define `apply` as its prototype method which is supplied with compiler as its argument + apply(compiler) { + // Specify the event hook to attach to + compiler.hooks.emit.tapAsync( + 'MyExampleWebpackPlugin', + (compilation, callback) => { + console.log('This is an example plugin!'); + console.log('Here’s the `compilation` object which represents a single build of assets:', compilation); + + // Manipulate the build using the plugin API provided by webpack + compilation.addModule(/* ... */); + + callback(); + } + ); + } +} +``` + +## Basic plugin architecture + +Plugins are instantiated objects with an `apply` method on their prototype. This `apply` method is called once by the webpack compiler while installing the plugin. The `apply` method is given a reference to the underlying webpack compiler, which grants access to compiler callbacks. A simple plugin is structured as follows: + +```javascript +class HelloWorldPlugin { + apply(compiler) { + compiler.hooks.done.tap('Hello World Plugin', ( + stats /* stats is passed as argument when done hook is tapped. */ + ) => { + console.log('Hello World!'); + }); + } +} + +module.exports = HelloWorldPlugin; +``` + +Then to use the plugin, include an instance in your webpack config `plugins` array: + +```javascript +// webpack.config.js +var HelloWorldPlugin = require('hello-world'); + +module.exports = { + // ... config settings here ... + plugins: [new HelloWorldPlugin({ options: true })] +}; +``` + +## Compiler and Compilation + +Among the two most important resources while developing plugins are the `compiler` and `compilation` objects. Understanding their roles is an important first step in extending the webpack engine. + +```javascript +class HelloCompilationPlugin { + apply(compiler) { + // Tap into compilation hook which gives compilation as argument to the callback function + compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => { + // Now we can tap into various hooks available through compilation + compilation.hooks.optimize.tap('HelloCompilationPlugin', () => { + console.log('Assets are being optimized.'); + }); + }); + } +} + +module.exports = HelloCompilationPlugin; +``` + +The list of hooks available on the `compiler`, `compilation`, and other important objects, see the [plugins API](/api/plugins/) docs. + +## Async event hooks + +Some plugin hooks are asynchronous. To tap into them, we can use `tap` method which will behave in synchronous manner or use one of `tapAsync` method or `tapPromise` method which are asynchronous methods. + +### tapAsync + +When we use `tapAsync` method to tap into plugins, we need to call the callback function which is supplied as the last argument to our function. + +```javascript +class HelloAsyncPlugin { + apply(compiler) { + compiler.hooks.emit.tapAsync('HelloAsyncPlugin', (compilation, callback) => { + // Do something async... + setTimeout(function() { + console.log('Done with async work...'); + callback(); + }, 1000); + }); + } +} + +module.exports = HelloAsyncPlugin; +``` + +#### tapPromise + +When we use `tapPromise` method to tap into plugins, we need to return a promise which resolves when our asynchronous task is completed. + +```javascript +class HelloAsyncPlugin { + apply(compiler) { + compiler.hooks.emit.tapPromise('HelloAsyncPlugin', compilation => { + // return a Promise that resolves when we are done... + return new Promise((resolve, reject) => { + setTimeout(function() { + console.log('Done with async work...'); + resolve(); + }, 1000); + }); + }); + } +} + +module.exports = HelloAsyncPlugin; +``` + +## Example + +Once we can latch onto the webpack compiler and each individual compilations, the possibilities become endless for what we can do with the engine itself. We can reformat existing files, create derivative files, or fabricate entirely new assets. + +Let's write a simple example plugin that generates a new build file called `filelist.md`; the contents of which will list all of the asset files in our build. This plugin might look something like this: + +```javascript +class FileListPlugin { + apply(compiler) { + // emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well + compiler.hooks.emit.tapAsync('FileListPlugin', (compilation, callback) => { + // Create a header string for the generated file: + var filelist = 'In this build:\n\n'; + + // Loop through all compiled assets, + // adding a new line item for each filename. + for (var filename in compilation.assets) { + filelist += '- ' + filename + '\n'; + } + + // Insert this list into the webpack build as a new file asset: + compilation.assets['filelist.md'] = { + source: function() { + return filelist; + }, + size: function() { + return filelist.length; + } + }; + + callback(); + }); + } +} + +module.exports = FileListPlugin; +``` + +## Different Plugin Shapes + +A plugin can be classified into types based on the event hooks it taps into. Every event hook is pre-defined as synchronous or asynchronous or waterfall or parallel hook and hook is called internally using call/callAsync method. The list of hooks that are supported or can be tapped into are generally specified in this.hooks property. + +For example:- + +```javascript +this.hooks = { + shouldEmit: new SyncBailHook(['compilation']) +}; +``` + +It represents that the only hook supported is `shouldEmit` which is a hook of `SyncBailHook` type and the only parameter which will be passed to any plugin that taps into `shouldEmit` hook is `compilation`. + +Various types of hooks supported are :- + +### Synchronous Hooks + +- __SyncHook__ + + - Defined as `new SyncHook([params])` + - Tapped into using `tap` method. + - Called using `call(...params)` method. + +- __Bail Hooks__ + + - Defined using `SyncBailHook[params]` + - Tapped into using `tap` method. + - Called using `call(...params)` method. + + In these type of hooks, each of the plugin callbacks will be invoked one after the other with the specific `args`. If any value is returned except undefined by any plugin, then that value is returned by hook and no further plugin callback is invoked. Many useful events like `optimizeChunks`, `optimizeChunkModules` are SyncBailHooks. + +- __Waterfall Hooks__ + + - Defined using `SyncWaterfallHook[params]` + - Tapped into using `tap` method. + - Called using `call( ... params)` method + + Here each of the plugins are called one after the other with the arguments from the return value of the previous plugin. The plugin must take the order of its execution into account. + It must accept arguments from the previous plugin that was executed. The value for the first plugin is `init`. Hence at least 1 param must be supplied for waterfall hooks. This pattern is used in the Tapable instances which are related to the webpack templates like `ModuleTemplate`, `ChunkTemplate` etc. + +### Asynchronous Hooks + +- __Async Series Hook__ + + - Defined using `AsyncSeriesHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + The plugin handler functions are called with all arguments and a callback function with the signature `(err?: Error) -> void`. The handler functions are called in order of registration. `callback` is called after all the handlers are called. + This is also a commonly used pattern for events like `emit`, `run`. + +- __Async waterfall__ The plugins will be applied asynchronously in the waterfall manner. + + - Defined using `AsyncWaterfallHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + The plugin handler functions are called with the current value and a callback function with the signature `(err: Error, nextValue: any) -> void.` When called `nextValue` is the current value for the next handler. The current value for the first handler is `init`. After all handlers are applied, callback is called with the last value. If any handler passes a value for `err`, the callback is called with this error and no more handlers are called. + This plugin pattern is expected for events like `before-resolve` and `after-resolve`. + +- __Async Series Bail__ + + - Defined using `AsyncSeriesBailHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + someMethod() { + // Call a hook: + this.hooks.compilation.call(); + +- __Async Parallel__ + + - Defined using `AsyncParallelHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + +- __Async Series Bail__ + + - Defined using `AsyncSeriesBailHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + +# Plugin Patterns + +Plugins grant unlimited opportunity to perform customizations within the webpack build system. This allows you to create custom asset types, perform unique build modifications, or even enhance the webpack runtime while using middleware. The following are some features of webpack that become useful while writing plugins. + +## Exploring assets, chunks, modules, and dependencies + +After a compilation is sealed, all structures within the compilation may be traversed. + +```javascript +class MyPlugin { + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + // Explore each chunk (build output): + compilation.chunks.forEach(chunk => { + // Explore each module within the chunk (built inputs): + chunk.modules.forEach(module => { + // Explore each source file path that was included into the module: + module.fileDependencies.forEach(filepath => { + // we've learned a lot about the source structure now... + }); + }); + + // Explore each asset filename generated by the chunk: + chunk.files.forEach(filename => { + // Get the asset source for each file generated by the chunk: + var source = compilation.assets[filename].source(); + }); + }); + + callback(); + }); + } +} +module.exports = MyPlugin; +``` + +- `compilation.modules`: An array of modules (built inputs) in the compilation. Each module manages the build of a raw file from your source library. +- `module.fileDependencies`: An array of source file paths included into a module. This includes the source JavaScript file itself (ex: `index.js`), and all dependency asset files (stylesheets, images, etc) that it has required. Reviewing dependencies is useful for seeing what source files belong to a module. +- `compilation.chunks`: An array of chunks (build outputs) in the compilation. Each chunk manages the composition of a final rendered assets. +- `chunk.modules`: An array of modules that are included into a chunk. By extension, you may look through each module's dependencies to see what raw source files fed into a chunk. +- `chunk.files`: An array of output filenames generated by the chunk. You may access these asset sources from the `compilation.assets` table. + +### Monitoring the watch graph + +While running webpack middleware, each compilation includes a `fileDependencies` array (what files are being watched) and a `fileTimestamps` hash that maps watched file paths to a timestamp. These are extremely useful for detecting what files have changed within the compilation: + +```javascript +class MyPlugin { + constructor() { + this.startTime = Date.now(); + this.prevTimestamps = {}; + } + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + var changedFiles = Object.keys(compilation.fileTimestamps).filter( + watchfile => { + return ( + (this.prevTimestamps[watchfile] || this.startTime) < + (compilation.fileTimestamps[watchfile] || Infinity) + ); + } + ); + + this.prevTimestamps = compilation.fileTimestamps; + callback(); + }); + } +} + +module.exports = MyPlugin; +``` + +You may also feed new file paths into the watch graph to receive compilation triggers when those files change. Simply push valid file paths into the `compilation.fileDependencies` array to add them to the watch. Note: the `fileDependencies` array is rebuilt in each compilation, so your plugin must push its own watched dependencies into each compilation to keep them under watch. + +## Changed chunks + +Similar to the watch graph, it's fairly simple to monitor changed chunks (or modules, for that matter) within a compilation by tracking their hashes. + +```javascript +class MyPlugin { + constructor() { + this.chunkVersions = {}; + } + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + var changedChunks = compilation.chunks.filter(chunk => { + var oldVersion = this.chunkVersions[chunk.name]; + this.chunkVersions[chunk.name] = chunk.hash; + return chunk.hash !== oldVersion; + }); + callback(); + }); + } +} + +module.exports = MyPlugin; +``` + + +# Release Process + +The release process for deploying webpack is actually quite painless. Read through the following steps, so you have a clear understanding of how it's done. + + +## Pull Requests + +When merging pull requests into the `master` branch, select the _Create Merge Commit_ option. + + +## Releasing + +```sh +npm version patch && git push --follow-tags && npm publish +npm version minor && git push --follow-tags && npm publish +npm version major && git push --follow-tags && npm publish +``` + +_This will increment the package version, commits the changes, cuts a __local tag__, push to github & publish the npm package._ + +After that go to the github [releases page](https://github.com/webpack/webpack/releases) and write a Changelog for the new tag. + + +# Debugging + +When contributing to the core repo, writing a loader/plugin, or even just working on complex project, debugging tools can be central to your workflow. Whether the problem is slow performance on a large project or an unhelpful traceback, the following utilities can make figuring it out less painful. + +- The [`stats` data](/api/stats) made available through [Node](/api/node#stats-object) and the [CLI](/api/cli#common-options). +- Chrome __DevTools__ via `node-nightly` and the latest Node.js versions. + + +## Stats + +Whether you want to sift through [this data](/api/stats) manually or use a tool to process it, the `stats` data can be extremely useful when debugging build issues. We won't go in depth here as there's an [entire page](/api/stats) dedicated to its contents, but know that you can use it to find the following information: + +- The contents of every module. +- The modules contained within every chunk. +- Per module compilation and resolving stats. +- Build errors and warnings. +- The relationships between modules. +- And much more... + +On top of that, the official [analyze tool](https://github.com/webpack/analyse) and [various others](/guides/code-splitting#bundle-analysis) will accept this data and visualize it in various ways. + + +## DevTools + +While [`console`](https://nodejs.org/api/console.html) statements may work well in simpler scenarios, sometimes a more robust solution is needed. As most front-end developers already know, Chrome DevTools are a life saver when debugging web applications, _but they don’t have to stop there_. As of Node v6.3.0+, developers can use the built-in `--inspect` flag to debug a node program in DevTools. + +This gives you the power to easily create breakpoints, debug memory usage, expose and examine objects in the console, and much more. In this short demo, we'll utilize the [`node-nightly`](https://github.com/hemanth/node-nightly) package which provides access to the latest and greatest inspecting capabilities. + +W> The `--inspect` interface has been available since v6.3.0 so feel to try it out with your local version, but be warned that certain features and flags may differ from the ones in this demo. + +Let's start by installing it globally: + +``` bash +npm install --global node-nightly +``` + +Now, we'll need to run it once to finish the installation: + +``` bash +node-nightly +``` + +Now, we can simply use `node-nightly` along with the `--inspect` flag to start our build in any webpack-based project. Note that we cannot run NPM `scripts`, e.g. `npm run build`, so we'll have specify the full `node_modules` path: + +``` bash +node-nightly --inspect ./node_modules/webpack/bin/webpack.js +``` + +Which should output something like: + +``` bash +Debugger listening on ws://127.0.0.1:9229/c624201a-250f-416e-a018-300bbec7be2c +For help see https://nodejs.org/en/docs/inspector +``` + +Now jump to `chrome://inspect` in the browser and you should see any active scripts you've inspected under the _Remote Target_ header. Click the "inspect" link under each script to open a dedicated debugger or the _Open dedicated DevTools for Node_ link for a session that will connect automatically. You can also check out the [NiM extension](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj), a handy Chrome plugin that will automatically open a DevTools tab every time you `--inspect` a script. + +We recommend using the `--inspect-brk` flag which will break on the first statement of the script allowing you to go through the source to set breakpoints and start/stop the build as you please. Also, don't forget that you can still pass arguments to the script. For example, if you have multiple configuration files you could pass `--config webpack.prod.js` to specify the configuration you'd like to debug. diff --git a/src/content/guides/_guides_all.md b/src/content/guides/_guides_all.md new file mode 100644 index 000000000000..dab542340ea2 --- /dev/null +++ b/src/content/guides/_guides_all.md @@ -0,0 +1,4880 @@ + + +# Installation + +This guide goes through the various methods used to install webpack. + + +## Prerequisites + +Before we begin, make sure you have a fresh version of [Node.js](https://nodejs.org/en/) installed. The current Long Term Support (LTS) release is an ideal starting point. You may run into a variety of issues with the older versions as they may be missing functionality webpack and/or its related packages require. + + +## Local Installation + +The latest webpack release is: + +[](https://github.com/webpack/webpack/releases) + +To install the latest release or a specific version, run one of the following commands: + +``` bash +npm install --save-dev webpack +npm install --save-dev webpack@<version> +``` + +If you're using webpack v4 or later, you'll need to install the [CLI](/api/cli/). + +``` bash +npm install --save-dev webpack-cli +``` + +Installing locally is what we recommend for most projects. This makes it easier to upgrade projects individually when breaking changes are introduced. Typically webpack is run via one or more [npm scripts](https://docs.npmjs.com/misc/scripts) which will look for a webpack installation in your local `node_modules` directory: + +```json +"scripts": { + "start": "webpack --config webpack.config.js" +} +``` + +T> To run the local installation of webpack you can access its bin version as `node_modules/.bin/webpack`. + + +## Global Installation + +The following NPM installation will make `webpack` available globally: + +``` bash +npm install --global webpack +``` + +W> Note that this is __not a recommended practice__. Installing globally locks you down to a specific version of webpack and could fail in projects that use a different version. + + +## Bleeding Edge + +If you are enthusiastic about using the latest that webpack has to offer, you can install beta versions or even directly from the webpack repository using the following commands: + +``` bash +npm install webpack@beta +npm install webpack/webpack#<tagname/branchname> +``` + +W> Take caution when installing these bleeding edge releases! They may still contain bugs and therefore should not be used in production. + + +# Getting Started + +Webpack is used to compile JavaScript modules. Once [installed](/guides/installation), you can interface with webpack either from its [CLI](/api/cli) or [API](/api/node). If you're still new to webpack, please read through the [core concepts](/concepts) and [this comparison](/comparison) to learn why you might use it over the other tools that are out in the community. + +## Basic Setup + +First let's create a directory, initialize npm, [install webpack locally](/guides/installation#local-installation), and install the webpack-cli (the tool used to run webpack on the command line): + +``` bash +mkdir webpack-demo && cd webpack-demo +npm init -y +npm install webpack webpack-cli --save-dev +``` + +T> Throughout the Guides we will use `diff` blocks to show you what changes we're making to directories, files, and code. + +Now we'll create the following directory structure, files and their contents: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- index.html ++ |- /src ++ |- index.js +``` + +__src/index.js__ + +``` javascript +function component() { + let element = document.createElement('div'); + + // Lodash, currently included via a script, is required for this line to work + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; +} + +document.body.appendChild(component()); +``` + +__index.html__ + +``` html +<!doctype html> +<html> + <head> + <title>Getting Started</title> + <script src="https://unpkg.com/lodash@4.16.6"></script> + </head> + <body> + <script src="./src/index.js"></script> + </body> +</html> +``` + +We also need to adjust our `package.json` file in order to make sure we mark our package as `private`, as well as removing the `main` entry. This is to prevent an accidental publish of your code. + +T> If you want to learn more about the inner workings of `package.json`, then we recommend reading the [npm documentation](https://docs.npmjs.com/files/package.json). + +__package.json__ + +``` diff + { + "name": "webpack-demo", + "version": "1.0.0", + "description": "", ++ "private": true, +- "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "webpack": "^4.20.2", + "webpack-cli": "^3.1.2" + }, + "dependencies": {} + } +``` + +In this example, there are implicit dependencies between the `<script>` tags. Our `index.js` file depends on `lodash` being included in the page before it runs. This is because `index.js` never explicitly declared a need for `lodash`; it just assumes that the global variable `_` exists. + +There are problems with managing JavaScript projects this way: + +- It is not immediately apparent that the script depends on an external library. +- If a dependency is missing, or included in the wrong order, the application will not function properly. +- If a dependency is included but not used, the browser will be forced to download unnecessary code. + +Let's use webpack to manage these scripts instead. + +## Creating a Bundle + +First we'll tweak our directory structure slightly, separating the "source" code (`/src`) from our "distribution" code (`/dist`). The "source" code is the code that we'll write and edit. The "distribution" code is the minimized and optimized `output` of our build process that will eventually be loaded in the browser: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- /dist ++ |- index.html +- |- index.html + |- /src + |- index.js +``` + +To bundle the `lodash` dependency with `index.js`, we'll need to install the library locally: + +``` bash +npm install --save lodash +``` + +T> When installing a package that will be bundled into your production bundle, you should use `npm install --save`. If you're installing a package for development purposes (e.g. a linter, testing libraries, etc.) then you should use `npm install --save-dev`. More information can be found in the [npm documentation](https://docs.npmjs.com/cli/install). + +Now, lets import `lodash` in our script: + +__src/index.js__ + +``` diff ++ import _ from 'lodash'; ++ + function component() { + let element = document.createElement('div'); + +- // Lodash, currently included via a script, is required for this line to work + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +Now, since we'll be bundling our scripts, we have to update our `index.html` file. Let's remove the lodash `<script>`, as we now `import` it, and modify the other `<script>` tag to load the bundle, instead of the raw `/src` file: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> + <title>Getting Started</title> +- <script src="https://unpkg.com/lodash@4.16.6"></script> + </head> + <body> +- <script src="./src/index.js"></script> ++ <script src="main.js"></script> + </body> + </html> +``` + +In this setup, `index.js` explicitly requires `lodash` to be present, and binds it as `_` (no global scope pollution). By stating what dependencies a module needs, webpack can use this information to build a dependency graph. It then uses the graph to generate an optimized bundle where scripts will be executed in the correct order. + +With that said, let's run `npx webpack`, which will take our script at `src/index.js` as the [entry point](/concepts/entry-points), and will generate `dist/main.js` as the [output](/concepts/output). The `npx` command, which ships with Node 8.2/npm 5.2.0 or higher, runs the webpack binary (`./node_modules/.bin/webpack`) of the webpack package we installed in the beginning: + +``` bash +npx webpack + +... +Built at: 13/06/2018 11:52:07 + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ +``` + +T> Your output may vary a bit, but if the build is successful then you are good to go. Also, don't worry about the warning, we'll tackle that later. + +Open `index.html` in your browser and, if everything went right, you should see the following text: 'Hello webpack'. + + +## Modules + +The [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) statements have been standardized in [ES2015](https://babeljs.io/learn-es2015/) and [are supported in most browsers](https://caniuse.com/#search=modules). Some older browsers still lag behind but webpack supports modules out of the box. + +Behind the scenes, webpack actually "transpiles" the code so that older browsers can also run it. If you inspect `dist/main.js`, you might be able to see how webpack does this, it's quite ingenious! Besides `import` and `export`, webpack supports various other module syntaxes as well, see [Module API](/api/module-methods) for more information. + +Note that webpack will not alter any code other than `import` and `export` statements. If you are using other [ES2015 features](http://es6-features.org/), make sure to [use a transpiler](/loaders/#transpiling) such as [Babel](https://babeljs.io/) or [Bublé](https://buble.surge.sh/guide/) via webpack's [loader system](/concepts/loaders/). + + +## Using a Configuration + +As of version 4, webpack doesn't require any configuration, but most projects will need a more complex setup, which is why webpack supports a [configuration file](/concepts/configuration). This is much more efficient than having to manually type in a lot of commands in the terminal, so let's create one: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- webpack.config.js + |- /dist + |- index.html + |- /src + |- index.js +``` + +__webpack.config.js__ + +``` javascript +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'main.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +Now, let's run the build again but instead using our new configuration file: + +``` bash +npx webpack --config webpack.config.js + +... + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ +``` + +T> If a `webpack.config.js` is present, the `webpack` command picks it up by default. We use the `--config` option here only to show that you can pass a config of any name. This will be useful for more complex configurations that need to be split into multiple files. + +A configuration file allows far more flexibility than simple CLI usage. We can specify loader rules, plugins, resolve options and many other enhancements this way. See the [configuration documentation](/configuration) to learn more. + + +## NPM Scripts + +Given it's not particularly fun to run a local copy of webpack from the CLI, we can set up a little shortcut. Let's adjust our _package.json_ by adding an [npm script](https://docs.npmjs.com/misc/scripts): + +__package.json__ + +``` diff + { + "name": "webpack-demo", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", ++ "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "webpack": "^4.20.2", + "webpack-cli": "^3.1.2" + }, + "dependencies": { + "lodash": "^4.17.5" + } + } +``` + +Now the `npm run build` command can be used in place of the `npx` command we used earlier. Note that within `scripts` we can reference locally installed npm packages by name the same way we did with `npx`. This convention is the standard in most npm-based projects because it allows all contributors to use the same set of common scripts (each with flags like `--config` if necessary). + +Now run the following command and see if your script alias works: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/. +``` + +T> Custom parameters can be passed to webpack by adding two dashes between the `npm run build` command and your parameters, e.g. `npm run build -- --colors`. + + +## Conclusion + +Now that you have a basic build together you should move on to the next guide [`Asset Management`](/guides/asset-management) to learn how to manage assets like images and fonts with webpack. At this point, your project should look like this: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist + |- main.js + |- index.html +|- /src + |- index.js +|- /node_modules +``` + +T> If you're using npm 5, you'll probably also see a `package-lock.json` file in your directory. + +If you want to learn more about webpack's design, you can check out the [basic concepts](/concepts) and [configuration](/configuration) pages. Furthermore, the [API](/api) section digs into the various interfaces webpack offers. + + +# Asset Management + +If you've been following the guides from the start, you will now have a small project that shows "Hello webpack". Now let's try to incorporate some other assets, like images, to see how they can be handled. + +Prior to webpack, front-end developers would use tools like grunt and gulp to process these assets and move them from their `/src` folder into their `/dist` or `/build` directory. The same idea was used for JavaScript modules, but tools like webpack will __dynamically bundle__ all dependencies (creating what's known as a [dependency graph](/concepts/dependency-graph)). This is great because every module now _explicitly states its dependencies_ and we'll avoid bundling modules that aren't in use. + +One of the coolest webpack features is that you can also _include any other type of file_, besides JavaScript, for which there is a loader. This means that the same benefits listed above for JavaScript (e.g. explicit dependencies) can be applied to everything used in building a website or web app. Let's start with CSS, as you may already be familiar with that setup. + +## Setup + +Let's make a minor change to our project before we get started: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> +- <title>Getting Started</title> ++ <title>Asset Management</title> + </head> + <body> +- <script src="./main.js"></script> ++ <script src="./bundle.js"></script> + </body> + </html> +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { +- filename: 'main.js', ++ filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + + +## Loading CSS + +In order to `import` a CSS file from within a JavaScript module, you need to install and add the [style-loader](/loaders/style-loader) and [css-loader](/loaders/css-loader) to your [`module` configuration](/configuration/module): + +``` bash +npm install --save-dev style-loader css-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ module: { ++ rules: [ ++ { ++ test: /\.css$/, ++ use: [ ++ 'style-loader', ++ 'css-loader' ++ ] ++ } ++ ] ++ } + }; +``` + +T> webpack uses a regular expression to determine which files it should look for and serve to a specific loader. In this case any file that ends with `.css` will be served to the `style-loader` and the `css-loader`. + +This enables you to `import './style.css'` into the file that depends on that styling. Now, when that module is run, a `<style>` tag with the stringified css will be inserted into the `<head>` of your html file. + +Let's try it out by adding a new `style.css` file to our project and import it in our `index.js`: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- style.css + |- index.js + |- /node_modules +``` + +__src/style.css__ + +``` css +.hello { + color: red; +} +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import './style.css'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.classList.add('hello'); + + return element; + } + + document.body.appendChild(component()); +``` + +Now run your build command: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +bundle.js 76.4 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +Open up `index.html` in your browser again and you should see that `Hello webpack` is now styled in red. To see what webpack did, inspect the page (don't view the page source, as it won't show you the result) and look at the page's head tags. It should contain our style block that we imported in `index.js`. + +Note that you can, and in most cases should, [minimize css](/plugins/mini-css-extract-plugin/#minimizing-for-production) for better load times in production. On top of that, loaders exist for pretty much any flavor of CSS you can think of -- [postcss](/loaders/postcss-loader), [sass](/loaders/sass-loader), and [less](/loaders/less-loader) to name a few. + + +## Loading Images + +So now we're pulling in our CSS, but what about our images like backgrounds and icons? Using the [file-loader](/loaders/file-loader) we can easily incorporate those in our system as well: + +``` bash +npm install --save-dev file-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, ++ { ++ test: /\.(png|svg|jpg|gif)$/, ++ use: [ ++ 'file-loader' ++ ] ++ } + ] + } + }; +``` + +Now, when you `import MyImage from './my-image.png'`, that image will be processed and added to your `output` directory _and_ the `MyImage` variable will contain the final url of that image after processing. When using the [css-loader](/loaders/css-loader), as shown above, a similar process will occur for `url('./my-image.png')` within your CSS. The loader will recognize this is a local file, and replace the `'./my-image.png'` path with the final path to the image in your `output` directory. The [html-loader](/loaders/html-loader) handles `<img src="./my-image.png" />` in the same manner. + +Let's add an image to our project and see how this works, you can use any image you like: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; + import './style.css'; ++ import Icon from './icon.png'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + element.classList.add('hello'); + ++ // Add the image to our existing div. ++ var myIcon = new Image(); ++ myIcon.src = Icon; ++ ++ element.appendChild(myIcon); + + return element; + } + + document.body.appendChild(component()); +``` + +__src/style.css__ + +``` diff + .hello { + color: red; ++ background: url('./icon.png'); + } +``` + +Let's create a new build and open up the index.html file again: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] + bundle.js 76.7 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +If all went well, you should now see your icon as a repeating background, as well as an `img` element beside our `Hello webpack` text. If you inspect this element, you'll see that the actual filename has changed to something like `5c999da72346a995e7e2718865d019c8.png`. This means webpack found our file in the `src` folder and processed it! + +T> A logical next step from here is minifying and optimizing your images. Check out the [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader) and [url-loader](/loaders/url-loader) for more on how you can enhance your image loading process. + + +## Loading Fonts + +So what about other assets like fonts? The file and url loaders will take any file you load through them and output it to your build directory. This means we can use them for any kind of file, including fonts. Let's update our `webpack.config.js` to handle font files: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + }, ++ { ++ test: /\.(woff|woff2|eot|ttf|otf)$/, ++ use: [ ++ 'file-loader' ++ ] ++ } + ] + } + }; +``` + +Add some font files to your project: + +__project__ + + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- my-font.woff ++ |- my-font.woff2 + |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +With the loader configured and fonts in place, you can incorporate them via an `@font-face` declaration. The local `url(...)` directive will be picked up by webpack just as it was with the image: + +__src/style.css__ + +``` diff ++ @font-face { ++ font-family: 'MyFont'; ++ src: url('./my-font.woff2') format('woff2'), ++ url('./my-font.woff') format('woff'); ++ font-weight: 600; ++ font-style: normal; ++ } + + .hello { + color: red; ++ font-family: 'MyFont'; + background: url('./icon.png'); + } +``` + +Now run a new build and let's see if webpack handled our fonts: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +5439466351d432b73fdb518c6ae9654a.woff2 19.5 KiB [emitted] + 387c65cc923ad19790469cfb5b7cb583.woff 23.4 KiB [emitted] + da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] + bundle.js 77 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +Open up `index.html` again and see if our `Hello webpack` text has changed to the new font. If all is well, you should see the changes. + + +## Loading Data + +Another useful asset that can be loaded is data, like JSON files, CSVs, TSVs, and XML. Support for JSON is actually built-in, similar to NodeJS, meaning `import Data from './data.json'` will work by default. To import CSVs, TSVs, and XML you could use the [csv-loader](https://github.com/theplatapi/csv-loader) and [xml-loader](https://github.com/gisikw/xml-loader). Let's handle loading all three: + +``` bash +npm install --save-dev csv-loader xml-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + }, + { + test: /\.(woff|woff2|eot|ttf|otf)$/, + use: [ + 'file-loader' + ] + }, ++ { ++ test: /\.(csv|tsv)$/, ++ use: [ ++ 'csv-loader' ++ ] ++ }, ++ { ++ test: /\.xml$/, ++ use: [ ++ 'xml-loader' ++ ] ++ } + ] + } + }; +``` + +Add some data files to your project: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- data.xml + |- my-font.woff + |- my-font.woff2 + |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +__src/data.xml__ + +``` xml +<?xml version="1.0" encoding="UTF-8"?> +<note> + <to>Mary</to> + <from>John</from> + <heading>Reminder</heading> + <body>Call Cindy on Tuesday</body> +</note> +``` + +Now you can `import` any one of those four types of data (JSON, CSV, TSV, XML) and the `Data` variable you import it to will contain parsed JSON for easy consumption: + +__src/index.js__ + +``` diff + import _ from 'lodash'; + import './style.css'; + import Icon from './icon.png'; ++ import Data from './data.xml'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + element.classList.add('hello'); + + // Add the image to our existing div. + var myIcon = new Image(); + myIcon.src = Icon; + + element.appendChild(myIcon); + ++ console.log(Data); + + return element; + } + + document.body.appendChild(component()); +``` + +When you open `index.html` and look at your console in your developer tools, you should be able to see your imported data being logged to the console! + +T> This can be especially helpful when implementing some sort of data visualization using a tool like [d3](https://github.com/d3). Instead of making an ajax request and parsing the data at runtime you can load it into your module during the build process so that the parsed data is ready to go as soon as the module hits the browser. + + +## Global Assets + +The coolest part of everything mentioned above, is that loading assets this way allows you to group modules and assets together in a more intuitive way. Instead of relying on a global `/assets` directory that contains everything, you can group assets with the code that uses them. For example, a structure like this can be very useful: + +``` diff +- |- /assets ++ |– /components ++ | |– /my-component ++ | | |– index.jsx ++ | | |– index.css ++ | | |– icon.svg ++ | | |– img.png +``` + +This setup makes your code a lot more portable as everything that is closely coupled now lives together. Let's say you want to use `/my-component` in another project, simply copy or move it into the `/components` directory over there. As long as you've installed any _external dependencies_ and your _configuration has the same loaders_ defined, you should be good to go. + +However, let's say you're locked into your old ways or you have some assets that are shared between multiple components (views, templates, modules, etc.). It's still possible to store these assets in a base directory and even use [aliasing](/configuration/resolve#resolve-alias) to make them easier to `import`. + + +## Wrapping up + +For the next guides we won't be using all the different assets we've used in this guide, so let's do some cleanup so we're prepared for the next piece of the guides [Output Management](https://webpack.js.org/guides/output-management/): + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src +- |- data.xml +- |- my-font.woff +- |- my-font.woff2 +- |- icon.png +- |- style.css + |- index.js + |- /node_modules +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- module: { +- rules: [ +- { +- test: /\.css$/, +- use: [ +- 'style-loader', +- 'css-loader' +- ] +- }, +- { +- test: /\.(png|svg|jpg|gif)$/, +- use: [ +- 'file-loader' +- ] +- }, +- { +- test: /\.(woff|woff2|eot|ttf|otf)$/, +- use: [ +- 'file-loader' +- ] +- }, +- { +- test: /\.(csv|tsv)$/, +- use: [ +- 'csv-loader' +- ] +- }, +- { +- test: /\.xml$/, +- use: [ +- 'xml-loader' +- ] +- } +- ] +- } + }; +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; +- import './style.css'; +- import Icon from './icon.png'; +- import Data from './data.xml'; +- + function component() { + var element = document.createElement('div'); +- +- // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- element.classList.add('hello'); +- +- // Add the image to our existing div. +- var myIcon = new Image(); +- myIcon.src = Icon; +- +- element.appendChild(myIcon); +- +- console.log(Data); + + return element; + } + + document.body.appendChild(component()); +``` + + +## Next guide + +Let's move on to [Output Management](https://webpack.js.org/guides/output-management/) + + +## Further Reading + +- [Loading Fonts](https://survivejs.com/webpack/loading/fonts/) on SurviveJS + + +# Output Management + +T> This guide extends on code examples found in the [`Asset Management`](/guides/asset-management) guide. + +So far we've manually included all our assets in our `index.html` file, but as your application grows and once you start [using hashes in filenames](/guides/caching) and outputting [multiple bundles](/guides/code-splitting), it will be difficult to keep managing your `index.html` file manually. However, a few plugins exist that will make this process much easier to manage. + +## Preparation + +First, let's adjust our project a little bit: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js ++ |- print.js + |- /node_modules +``` + +Let's add some logic to our `src/print.js` file: + +__src/print.js__ + +``` js +export default function printMe() { + console.log('I get called from print.js!'); +} +``` + +And use that function in our `src/index.js` file: + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); ++ var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + ++ btn.innerHTML = 'Click me and check the console!'; ++ btn.onclick = printMe; ++ ++ element.appendChild(btn); + + return element; + } + + document.body.appendChild(component()); +``` + +Let's also update our `dist/index.html` file, in preparation for webpack to split out entries: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> +- <title>Asset Management</title> ++ <title>Output Management</title> ++ <script src="./print.bundle.js"></script> + </head> + <body> +- <script src="./bundle.js"></script> ++ <script src="./app.bundle.js"></script> + </body> + </html> +``` + +Now adjust the config. We'll be adding our `src/print.js` as a new entry point (`print`) and we'll change the output as well, so that it will dynamically generate bundle names, based on the entry point names: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { +- entry: './src/index.js', ++ entry: { ++ app: './src/index.js', ++ print: './src/print.js' ++ }, + output: { +- filename: 'bundle.js', ++ filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Let's run `npm run build` and see what this generates: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 545 kB 0, 1 [emitted] [big] app +print.bundle.js 2.74 kB 1 [emitted] print +... +``` + +We can see that webpack generates our `print.bundle.js` and `app.bundle.js` files, which we also specified in our `index.html` file. if you open `index.html` in your browser, you can see what happens when you click the button. + +But what would happen if we changed the name of one of our entry points, or even added a new one? The generated bundles would be renamed on a build, but our `index.html` file would still reference the old names. Let's fix that with the [`HtmlWebpackPlugin`](/plugins/html-webpack-plugin). + + +## Setting up HtmlWebpackPlugin + +First install the plugin and adjust the `webpack.config.js` file: + +``` bash +npm install --save-dev html-webpack-plugin +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, ++ plugins: [ ++ new HtmlWebpackPlugin({ ++ title: 'Output Management' ++ }) ++ ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Before we do a build, you should know that the `HtmlWebpackPlugin` by default will generate its own `index.html` file, even though we already have one in the `dist/` folder. This means that it will replace our `index.html` file with a newly generated one. Let's see what happens when we do an `npm run build`: + +``` bash +... + Asset Size Chunks Chunk Names + print.bundle.js 544 kB 0 [emitted] [big] print + app.bundle.js 2.81 kB 1 [emitted] app + index.html 249 bytes [emitted] +... +``` + +If you open `index.html` in your code editor, you'll see that the `HtmlWebpackPlugin` has created an entirely new file for you and that all the bundles are automatically added. + +If you want to learn more about all the features and options that the `HtmlWebpackPlugin` provides, then you should read up on it on the [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin) repo. + +You can also take a look at [`html-webpack-template`](https://github.com/jaketrent/html-webpack-template) which provides a couple of extra features in addition to the default template. + + +## Cleaning up the `/dist` folder + +As you might have noticed over the past guides and code example, our `/dist` folder has become quite cluttered. Webpack will generate the files and put them in the `/dist` folder for you, but it doesn't keep track of which files are actually in use by your project. + +In general it's good practice to clean the `/dist` folder before each build, so that only used files will be generated. Let's take care of that. + +A popular plugin to manage this is the [`clean-webpack-plugin`](https://www.npmjs.com/package/clean-webpack-plugin) so let's install and configure it. + +``` bash +npm install --save-dev clean-webpack-plugin +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); ++ const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ ++ new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Output Management' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Now run an `npm run build` and inspect the `/dist` folder. If everything went well you should now only see the files generated from the build and no more old files! + + +## The Manifest + +You might be wondering how webpack and its plugins seem to "know" what files are being generated. The answer is in the manifest that webpack keeps to track how all the modules map to the output bundles. If you're interested in managing webpack's [`output`](/configuration/output) in other ways, the manifest would be a good place to start. + +The manifest data can be extracted into a json file for easy consumption using the [`WebpackManifestPlugin`](https://github.com/danethurber/webpack-manifest-plugin). + +We won't go through a full example of how to use this plugin within your projects, but you can read up on [the concept page](/concepts/manifest) and the [caching guide](/guides/caching) to find out how this ties into long term caching. + + +## Conclusion + +Now that you've learned about dynamically adding bundles to your HTML, let's dive into the [development guide](/guides/development). Or, if you want to dig into more advanced topics, we would recommend heading over to the [code splitting guide](/guides/code-splitting). + + +# Development + +T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. + +If you've been following the guides, you should have a solid understanding of some of the webpack basics. Before we continue, let's look into setting up a development environment to make our lives a little easier. + +W> The tools in this guide are __only meant for development__, please __avoid__ using them in production! + +Before proceeding lets first set [`mode` to `'development'`](/concepts/mode/#mode-development). + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { ++ mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +## Using source maps + +When webpack bundles your source code, it can become difficult to track down errors and warnings to their original location. For example, if you bundle three source files (`a.js`, `b.js`, and `c.js`) into one bundle (`bundle.js`) and one of the source files contains an error, the stack trace will simply point to `bundle.js`. This isn't always helpful as you probably want to know exactly which source file the error came from. + +In order to make it easier to track down errors and warnings, JavaScript offers [source maps](http://blog.teamtreehouse.com/introduction-source-maps), which maps your compiled code back to your original source code. If an error originates from `b.js`, the source map will tell you exactly that. + +There are a lot of [different options](/configuration/devtool) available when it comes to source maps. Be sure to check them out so you can configure them to your needs. + +For this guide, let's use the `inline-source-map` option, which is good for illustrative purposes (though not for production): + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, ++ devtool: 'inline-source-map', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Now let's make sure we have something to debug, so let's create an error in our `print.js` file: + +__src/print.js__ + +``` diff + export default function printMe() { +- console.log('I get called from print.js!'); ++ cosnole.log('I get called from print.js!'); + } +``` + +Run an `npm run build`, it should compile to something like this: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 1.44 MB 0, 1 [emitted] [big] app +print.bundle.js 6.43 kB 1 [emitted] print + index.html 248 bytes [emitted] +... +``` + +Now open the resulting `index.html` file in your browser. Click the button and look in your console where the error is displayed. The error should say something like this: + + ``` bash + Uncaught ReferenceError: cosnole is not defined + at HTMLButtonElement.printMe (print.js:2) + ``` + +We can see that the error also contains a reference to the file (`print.js`) and line number (2) where the error occurred. This is great because now we know exactly where to look in order to fix the issue. + + +## Choosing a Development Tool + +W> Some text editors have a "safe write" function that might interfere with some of the following tools. Read [Adjusting Your text Editor](#adjusting-your-text-editor) for a solution to these issues. + +It quickly becomes a hassle to manually run `npm run build` every time you want to compile your code. + +There are a couple of different options available in webpack that help you automatically compile your code whenever it changes: + + 1. webpack's Watch Mode + 2. webpack-dev-server + 3. webpack-dev-middleware + +In most cases, you probably would want to use `webpack-dev-server`, but let's explore all of the above options. + + +### Using Watch Mode + +You can instruct webpack to "watch" all files within your dependency graph for changes. If one of these files is updated, the code will be recompiled so you don't have to run the full build manually. + +Let's add an npm script that will start webpack's Watch Mode: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", ++ "watch": "webpack --watch", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now run `npm run watch` from the command line and see how webpack compiles your code. +You can see that it doesn't exit the command line because the script is currently watching your files. + +Now, while webpack is watching your files, let's remove the error we introduced earlier: + +__src/print.js__ + +``` diff + export default function printMe() { +- cosnole.log('I get called from print.js!'); ++ console.log('I get called from print.js!'); + } +``` + +Now save your file and check the terminal window. You should see that webpack automatically recompiles the changed module! + +The only downside is that you have to refresh your browser in order to see the changes. It would be much nicer if that would happen automatically as well, so let's try `webpack-dev-server` which will do exactly that. + + +### Using webpack-dev-server + +The `webpack-dev-server` provides you with a simple web server and the ability to use live reloading. Let's set it up: + +``` bash +npm install --save-dev webpack-dev-server +``` + +Change your config file to tell the dev server where to look for files: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + devtool: 'inline-source-map', ++ devServer: { ++ contentBase: './dist' ++ }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +This tells `webpack-dev-server` to serve the files from the `dist` directory on `localhost:8080`. + +W> webpack-dev-server doesn't write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server's root path. If your page expects to find the bundle files in different path, you can change this with the [`publicPath`](/configuration/dev-server/#devserver-publicpath-) option in the dev server's configuration. + +Let's add a script to easily run the dev server as well: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "watch": "webpack --watch", ++ "start": "webpack-dev-server --open", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now we can run `npm start` from the command line and we will see our browser automatically loading up our page. If you now change any of the source files and save them, the web server will automatically reload after the code has been compiled. Give it a try! + +The `webpack-dev-server` comes with many configurable options. Head over to the [documentation](/configuration/dev-server) to learn more. + +T> Now that your server is working, you might want to give [Hot Module Replacement](/guides/hot-module-replacement) a try! + + +### Using webpack-dev-middleware + +`webpack-dev-middleware` is a wrapper that will emit files processed by webpack to a server. This is used in `webpack-dev-server` internally, however it's available as a separate package to allow more custom setups if desired. We'll take a look at an example that combines webpack-dev-middleware with an express server. + +Let's install `express` and `webpack-dev-middleware` so we can get started: + +``` bash +npm install --save-dev express webpack-dev-middleware +``` + +Now we need to make some adjustments to our webpack configuration file in order to make sure the middleware will function correctly: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Output Management' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist'), ++ publicPath: '/' + } + }; +``` + +The `publicPath` will be used within our server script as well in order to make sure files are served correctly on `http://localhost:3000`. We'll specify the port number later. The next step is setting up our custom `express` server: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js ++ |- server.js + |- /dist + |- /src + |- index.js + |- print.js + |- /node_modules +``` + +__server.js__ + +```javascript +const express = require('express'); +const webpack = require('webpack'); +const webpackDevMiddleware = require('webpack-dev-middleware'); + +const app = express(); +const config = require('./webpack.config.js'); +const compiler = webpack(config); + +// Tell express to use the webpack-dev-middleware and use the webpack.config.js +// configuration file as a base. +app.use(webpackDevMiddleware(compiler, { + publicPath: config.output.publicPath +})); + +// Serve the files on port 3000. +app.listen(3000, function () { + console.log('Example app listening on port 3000!\n'); +}); +``` + +Now add an npm script to make it a little easier to run the server: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "watch": "webpack --watch", + "start": "webpack-dev-server --open", ++ "server": "node server.js", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "express": "^4.15.3", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "webpack-dev-middleware": "^1.12.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now in your terminal run `npm run server`, it should give you an output similar to this: + +``` bash +Example app listening on port 3000! +... + Asset Size Chunks Chunk Names + app.bundle.js 1.44 MB 0, 1 [emitted] [big] app +print.bundle.js 6.57 kB 1 [emitted] print + index.html 306 bytes [emitted] +... +webpack: Compiled successfully. +``` + +Now fire up your browser and go to `http://localhost:3000`. You should see your webpack app running and functioning! + +T> If you would like to know more about how Hot Module Replacement works, we recommend you read the [Hot Module Replacement](/guides/hot-module-replacement/) guide. + + +## Adjusting Your Text Editor + +When using automatic compilation of your code, you could run into issues when saving your files. Some editors have a "safe write" feature that can potentially interfere with recompilation. + +To disable this feature in some common editors, see the list below: + +- __Sublime Text 3__: Add `atomic_save: 'false'` to your user preferences. +- __JetBrains IDEs (e.g. WebStorm)__: Uncheck "Use safe write" in `Preferences > Appearance & Behavior > System Settings`. +- __Vim__: Add `:set backupcopy=yes` to your settings. + + +## Conclusion + +Now that you've learned how to automatically compile your code and run a simple development server, you can check out the next guide, which will cover [Hot Module Replacement](/guides/hot-module-replacement). + + +# Hot Module Replacement + +T> This guide extends on code examples found in the [Development](/guides/development) guide. + +Hot Module Replacement (or HMR) is one of the most useful features offered by webpack. It allows all kinds of modules to be updated at runtime without the need for a full refresh. This page focuses on __implementation__ while the [concepts page](/concepts/hot-module-replacement) gives more details on how it works and why it's useful. + +W> __HMR__ is not intended for use in production, meaning it should only be used in development. See the [building for production guide](/guides/production) for more information. + + +## Enabling HMR + +This feature is great for productivity. All we need to do is update our [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration, and use webpack's built in HMR plugin. We'll also remove the entry point for `print.js` as it will now be consumed by the `index.js` module. + +T> If you took the route of using `webpack-dev-middleware` instead of `webpack-dev-server`, please use the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom server or application. + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const webpack = require('webpack'); + + module.exports = { + entry: { +- app: './src/index.js', +- print: './src/print.js' ++ app: './src/index.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist', ++ hot: true + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Hot Module Replacement' + }), ++ new webpack.HotModuleReplacementPlugin() + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +T> You can use the CLI to modify the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration with the following command: `webpack-dev-server --hotOnly`. + +Now let's update the `index.js` file so that when a change inside `print.js` is detected we tell webpack to accept the updated module. + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; + + element.appendChild(btn); + + return element; + } + + document.body.appendChild(component()); ++ ++ if (module.hot) { ++ module.hot.accept('./print.js', function() { ++ console.log('Accepting the updated printMe module!'); ++ printMe(); ++ }) ++ } +``` + +Start changing the `console.log` statement in `print.js`, and you should see the following output in the browser console. + +__print.js__ + +``` diff + export default function printMe() { +- console.log('I get called from print.js!'); ++ console.log('Updating print.js...') + } +``` + +__console__ + +``` diff +[HMR] Waiting for update signal from WDS... +main.js:4395 [WDS] Hot Module Replacement enabled. ++ 2main.js:4395 [WDS] App updated. Recompiling... ++ main.js:4395 [WDS] App hot update... ++ main.js:4330 [HMR] Checking for updates on the server... ++ main.js:10024 Accepting the updated printMe module! ++ 0.4b8ee77….hot-update.js:10 Updating print.js... ++ main.js:4330 [HMR] Updated modules: ++ main.js:4330 [HMR] - 20 +``` + + +## Via the Node.js API + +When using Webpack Dev Server with the Node.js API, don't put the dev server options on the webpack config object. Instead, pass them as a second parameter upon creation. For example: + +`new WebpackDevServer(compiler, options)` + +To enable HMR, you also need to modify your webpack configuration object to include the HMR entry points. The `webpack-dev-server` package includes a method called `addDevServerEntrypoints` which you can use to do this. Here's a small example of how that might look: + +__dev-server.js__ + +``` javascript +const webpackDevServer = require('webpack-dev-server'); +const webpack = require('webpack'); + +const config = require('./webpack.config.js'); +const options = { + contentBase: './dist', + hot: true, + host: 'localhost' +}; + +webpackDevServer.addDevServerEntrypoints(config, options); +const compiler = webpack(config); +const server = new webpackDevServer(compiler, options); + +server.listen(5000, 'localhost', () => { + console.log('dev server listening on port 5000'); +}); +``` + +T> If you're [using `webpack-dev-middleware`](/guides/development#using-webpack-dev-middleware), check out the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom dev server. + + +## Gotchas + +Hot Module Replacement can be tricky. To show this, let's go back to our working example. If you go ahead and click the button on the example page, you will realize the console is printing the old `printMe` function. + +This is happening because the button's `onclick` event handler is still bound to the original `printMe` function. + +To make this work with HMR we need to update that binding to the new `printMe` function using `module.hot.accept`: + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; // onclick event is bind to the original printMe function + + element.appendChild(btn); + + return element; + } + +- document.body.appendChild(component()); ++ let element = component(); // Store the element to re-render on print.js changes ++ document.body.appendChild(element); + + if (module.hot) { + module.hot.accept('./print.js', function() { + console.log('Accepting the updated printMe module!'); +- printMe(); ++ document.body.removeChild(element); ++ element = component(); // Re-render the "component" to update the click handler ++ document.body.appendChild(element); + }) + } +``` + +This is just one example, but there are many others that can easily trip people up. Luckily, there are a lot of loaders out there (some of which are mentioned below) that will make hot module replacement much easier. + + +## HMR with Stylesheets + +Hot Module Replacement with CSS is actually fairly straightforward with the help of the `style-loader`. This loader uses `module.hot.accept` behind the scenes to patch `<style>` tags when CSS dependencies are updated. + +First let's install both loaders with the following command: + +```bash +npm install --save-dev style-loader css-loader +``` + +Now let's update the configuration file to make use of the loader. + +__webpack.config.js__ + +```diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const webpack = require('webpack'); + + module.exports = { + entry: { + app: './src/index.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist', + hot: true + }, ++ module: { ++ rules: [ ++ { ++ test: /\.css$/, ++ use: ['style-loader', 'css-loader'] ++ } ++ ] ++ }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Hot Module Replacement' + }), + new webpack.HotModuleReplacementPlugin() + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Hot loading stylesheets is as easy as importing them into a module: + +__project__ + +``` diff + webpack-demo + | - package.json + | - webpack.config.js + | - /dist + | - bundle.js + | - /src + | - index.js + | - print.js ++ | - styles.css +``` + +__styles.css__ + +``` css +body { + background: blue; +} +``` + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; ++ import './styles.css'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; // onclick event is bind to the original printMe function + + element.appendChild(btn); + + return element; + } + + let element = component(); + document.body.appendChild(element); + + if (module.hot) { + module.hot.accept('./print.js', function() { + console.log('Accepting the updated printMe module!'); + document.body.removeChild(element); + element = component(); // Re-render the "component" to update the click handler + document.body.appendChild(element); + }) + } + +``` + +Change the style on `body` to `background: red;` and you should immediately see the page's background color change without a full refresh. + +__styles.css__ + +``` diff + body { +- background: blue; ++ background: red; + } +``` + + +## Other Code and Frameworks + +There are many other loaders and examples out in the community to make HMR interact smoothly with a variety of frameworks and libraries... + +- [React Hot Loader](https://github.com/gaearon/react-hot-loader): Tweak react components in real time. +- [Vue Loader](https://github.com/vuejs/vue-loader): This loader supports HMR for vue components out of the box. +- [Elm Hot Loader](https://github.com/fluxxu/elm-hot-loader): Supports HMR for the Elm programming language. +- [Angular HMR](https://github.com/gdi2290/angular-hmr): No loader necessary! A simple change to your main NgModule file is all that's required to have full control over the HMR APIs. + +T> If you know of any other loaders or plugins that help with or enhance Hot Module Replacement please submit a pull request to add to this list! + + +# Tree Shaking + +_Tree shaking_ is a term commonly used in the JavaScript context for dead-code elimination. It relies on the [static structure](http://exploringjs.com/es6/ch_modules.html#static-module-structure) of ES2015 module syntax, i.e. [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export). The name and concept have been popularized by the ES2015 module bundler [rollup](https://github.com/rollup/rollup). + +The webpack 2 release came with built-in support for ES2015 modules (alias _harmony modules_) as well as unused module export detection. The new webpack 4 release expands on this capability with a way to provide hints to the compiler via the `"sideEffects"` `package.json` property to denote which files in your project are "pure" and therefore safe to prune if unused. + +T> The remainder of this guide will stem from [Getting Started](/guides/getting-started). If you haven't read through that guide already, please do so now. + + +## Add a Utility + +Let's add a new utility file to our project, `src/math.js`, that exports two functions: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist + |- bundle.js + |- index.html +|- /src + |- index.js ++ |- math.js +|- /node_modules +``` + +__src/math.js__ + +```javascript +export function square(x) { + return x * x; +} + +export function cube(x) { + return x * x * x; +} +``` + +Set the `mode` configuration option to [development](/concepts/mode/#mode-development) to make sure that the bundle is not minified: + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') +- } ++ }, ++ mode: 'development', ++ optimization: { ++ usedExports: true ++ } +}; +``` + +With that in place, let's update our entry script to utilize one of these new methods and remove `lodash` for simplicity: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; ++ import { cube } from './math.js'; + + function component() { +- var element = document.createElement('div'); ++ var element = document.createElement('pre'); + +- // Lodash, now imported by this script +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.innerHTML = [ ++ 'Hello webpack!', ++ '5 cubed is equal to ' + cube(5) ++ ].join('\n\n'); + + return element; + } + + document.body.appendChild(component()); +``` + +Note that we __did not `import` the `square` method__ from the `src/math.js` module. That function is what's known as "dead code", meaning an unused `export` that should be dropped. Now let's run our npm script, `npm run build`, and inspect the output bundle: + +__dist/bundle.js (around lines 90 - 100)__ + +```js +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + 'use strict'; + /* unused harmony export square */ + /* harmony export (immutable) */ __webpack_exports__['a'] = cube; + function square(x) { + return x * x; + } + + function cube(x) { + return x * x * x; + } +}); +``` + +Note the `unused harmony export square` comment above. If you look at the code below it, you'll notice that `square` is not being imported, however, it is still included in the bundle. We'll fix that in the next section. + + +## Mark the file as side-effect-free + +In a 100% ESM module world, identifying side effects is straightforward. However, we aren't there just yet, so in the mean time it's necessary to provide hints to webpack's compiler on the "pureness" of your code. + +The way this is accomplished is the `"sideEffects"` package.json property. + +```json +{ + "name": "your-project", + "sideEffects": false +} +``` + +All the code noted above does not contain side effects, so we can simply mark the property as `false` to inform webpack that it can safely prune unused exports. + +T> A "side effect" is defined as code that performs a special behavior when imported, other than exposing one or more exports. An example of this are polyfills, which affect the global scope and usually do not provide an export. + +If your code did have some side effects though, an array can be provided instead: + +```json +{ + "name": "your-project", + "sideEffects": [ + "./src/some-side-effectful-file.js" + ] +} +``` + +The array accepts relative, absolute, and glob patterns to the relevant files. It uses [micromatch](https://github.com/micromatch/micromatch#matching-features) under the hood. + +T> Note that any imported file is subject to tree shaking. This means if you use something like `css-loader` in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode: + +```json +{ + "name": "your-project", + "sideEffects": [ + "./src/some-side-effectful-file.js", + "*.css" + ] +} +``` + +Finally, `"sideEffects"` can also be set from the [`module.rules` configuration option](/configuration/module/#module-rules). + +## Minify the Output + +So we've cued up our "dead code" to be dropped by using the `import` and `export` syntax, but we still need to drop it from the bundle. To do that set the `mode` configuration option to [`production`](/concepts/mode/#mode-production) configuration option. + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- mode: 'development', +- optimization: { +- usedExports: true +- } ++ mode: 'production' +}; +``` + +T> Note that the `--optimize-minimize` flag can be used to enable `TerserPlugin` as well. + +With that squared away, we can run another `npm run build` and see if anything has changed. + +Notice anything different about `dist/bundle.js`? Clearly the whole bundle is now minified and mangled, but, if you look carefully, you won't see the `square` function included but will see a mangled version of the `cube` function (`function r(e){return e*e*e}n.a=r`). With minification and tree shaking our bundle is now a few bytes smaller! While that may not seem like much in this contrived example, tree shaking can yield a significant decrease in bundle size when working on larger applications with complex dependency trees. + +T> [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) is needed for the tree shaking to work. It is added by `mode: "production"`. If you are not using it, remember to add the [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) manually. + +## Conclusion + +So, what we've learned is that in order to take advantage of _tree shaking_, you must... + +- Use ES2015 module syntax (i.e. `import` and `export`). +- Ensure no compilers transform your ES2015 module syntax into CommonJS modules (this is the default behavior of popular Babel preset @babel/preset-env - see [documentation](https://babeljs.io/docs/en/babel-preset-env#modules) for more details). +- Add a `"sideEffects"` property to your project's `package.json` file. +- Use [`production`](/concepts/mode/#mode-production) `mode` configuration option to enable [various optimizations](/concepts/mode/#usage) including minification and tree shaking. + +You can imagine your application as a tree. The source code and libraries you actually use represent the green, living leaves of the tree. Dead code represents the brown, dead leaves of the tree that are consumed by autumn. In order to get rid of the dead leaves, you have to shake the tree, causing them to fall. + +If you are interested in more ways to optimize your output, please jump to the next guide for details on building for [production](/guides/production). + + +# Production + +In this guide we'll dive into some of the best practices and utilities for building a production site or application. + +T> This walkthrough stems from [Tree Shaking](/guides/tree-shaking) and [Development](/guides/development). Please ensure you are familiar with the concepts/setup introduced in those guides before continuing on. + + +## Setup + +The goals of _development_ and _production_ builds differ greatly. In _development_, we want strong source mapping and a localhost server with live reloading or hot module replacement. In _production_, our goals shift to a focus on minified bundles, lighter weight source maps, and optimized assets to improve load time. With this logical separation at hand, we typically recommend writing __separate webpack configurations__ for each environment. + +While we will separate the _production_ and _development_ specific bits out, note that we'll still maintain a "common" configuration to keep things DRY. In order to merge these configurations together, we'll use a utility called [`webpack-merge`](https://github.com/survivejs/webpack-merge). With the "common" configuration in place, we won't have to duplicate code within the environment-specific configurations. + +Let's start by installing `webpack-merge` and splitting out the bits we've already worked on in previous guides: + +``` bash +npm install --save-dev webpack-merge +``` + +__project__ + +``` diff + webpack-demo + |- package.json +- |- webpack.config.js ++ |- webpack.common.js ++ |- webpack.dev.js ++ |- webpack.prod.js + |- /dist + |- /src + |- index.js + |- math.js + |- /node_modules +``` + +__webpack.common.js__ + +``` diff ++ const path = require('path'); ++ const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const HtmlWebpackPlugin = require('html-webpack-plugin'); ++ ++ module.exports = { ++ entry: { ++ app: './src/index.js' ++ }, ++ plugins: [ ++ new CleanWebpackPlugin(['dist']), ++ new HtmlWebpackPlugin({ ++ title: 'Production' ++ }) ++ ], ++ output: { ++ filename: '[name].bundle.js', ++ path: path.resolve(__dirname, 'dist') ++ } ++ }; +``` + +__webpack.dev.js__ + +``` diff ++ const merge = require('webpack-merge'); ++ const common = require('./webpack.common.js'); ++ ++ module.exports = merge(common, { ++ mode: 'development', ++ devtool: 'inline-source-map', ++ devServer: { ++ contentBase: './dist' ++ } ++ }); +``` + +__webpack.prod.js__ + +``` diff ++ const merge = require('webpack-merge'); ++ const common = require('./webpack.common.js'); ++ ++ module.exports = merge(common, { ++ mode: 'production', ++ }); +``` + +In `webpack.common.js`, we now have setup our `entry` and `output` configuration and we've included any plugins that are required for both environments. In `webpack.dev.js`, we've set ``mode`` to ``development``. Also, we've added the recommended `devtool` for that environment (strong source mapping), as well as our simple `devServer` configuration. Finally, in `webpack.prod.js`,``mode`` is set to ``production`` which loads `TerserPlugin` which was first introduced by the [tree shaking](/guides/tree-shaking) guide. + +Note the use of `merge()` in the environment-specific configurations to easily include our common configuration in `dev` and `prod`. The `webpack-merge` tool offers a variety of advanced features for merging but for our use case we won't need any of that. + + +## NPM Scripts + +Now let's repoint our `scripts` to the new configurations. We'll use the _development_ one for our `webpack-dev-server`, `npm start`, script and the _production_ one for our `npm run build` script: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { +- "start": "webpack-dev-server --open", ++ "start": "webpack-dev-server --open --config webpack.dev.js", +- "build": "webpack" ++ "build": "webpack --config webpack.prod.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.17", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "express": "^4.15.3", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "webpack-dev-middleware": "^1.12.0", + "webpack-dev-server": "^2.9.1", + "webpack-merge": "^4.1.0", + "xml-loader": "^1.2.1" + } + } +``` + +Feel free to run those scripts and see how the output changes as we continue adding to our _production_ configuration. + + +## Specify the Mode + +Many libraries will key off the `process.env.NODE_ENV` variable to determine what should be included in the library. For example, when not in _production_ some libraries may add additional logging and testing to make debugging easier. However, with `process.env.NODE_ENV === 'production'` they might drop or add significant portions of code to optimize how things run for your actual users. Since webpack v4, specifying [`mode`](/concepts/mode/) automatically configures [`DefinePlugin`](/plugins/define-plugin) for you: + +__webpack.prod.js__ + +``` diff + const merge = require('webpack-merge'); + const common = require('./webpack.common.js'); + + module.exports = merge(common, { + mode: 'production', + }); +``` + +T> Technically, `NODE_ENV` is a system environment variable that Node.js exposes into running scripts. It is used by convention to determine dev-vs-prod behavior by server tools, build scripts, and client-side libraries. Contrary to expectations, `process.env.NODE_ENV` is not set to `"production"` __within__ the build script `webpack.config.js`, see [#2537](https://github.com/webpack/webpack/issues/2537). Thus, conditionals like `process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'` within webpack configurations do not work as expected. + +If you're using a library like [`react`](https://reactjs.org/), you should actually see a significant drop in bundle size after adding this plugin. Also note that any of our local `/src` code can key off of this as well, so the following check would be valid: + +__src/index.js__ + +``` diff + import { cube } from './math.js'; ++ ++ if (process.env.NODE_ENV !== 'production') { ++ console.log('Looks like we are in development mode!'); ++ } + + function component() { + var element = document.createElement('pre'); + + element.innerHTML = [ + 'Hello webpack!', + '5 cubed is equal to ' + cube(5) + ].join('\n\n'); + + return element; + } + + document.body.appendChild(component()); +``` + + +## Minification + +webpack v4+ will minify your code by default in [`production mode`](/concepts/mode/#mode-production). + +Note that while the [`TerserPlugin`](/plugins/terser-webpack-plugin) is a great place to start for minification and being used by default, there are other options out there. Here are a few more popular ones: + +- [`BabelMinifyWebpackPlugin`](https://github.com/webpack-contrib/babel-minify-webpack-plugin) +- [`ClosureCompilerPlugin`](https://github.com/roman01la/webpack-closure-compiler) + +If you decide to try another minification plugin, just make sure your new choice also drops dead code as described in the [tree shaking](/guides/tree-shaking) guide and provide it as the [`optimization.minimizer`](/configuration/optimization/#optimization-minimizer). + + +## Source Mapping + +We encourage you to have source maps enabled in production, as they are useful for debugging as well as running benchmark tests. That said, you should choose one with a fairly quick build speed that's recommended for production use (see [`devtool`](/configuration/devtool)). For this guide, we'll use the `source-map` option in _production_ as opposed to the `inline-source-map` we used in _development_: + +__webpack.prod.js__ + +``` diff + const merge = require('webpack-merge'); + const common = require('./webpack.common.js'); + + module.exports = merge(common, { + mode: 'production', ++ devtool: 'source-map' + }); +``` + +T> Avoid `inline-***` and `eval-***` use in production as they can increase bundle size and reduce the overall performance. + + +## Minimize CSS + +It is crucial to minimize your CSS on production, please see [Minimizing for Production](/plugins/mini-css-extract-plugin/#minimizing-for-production) section. + + +## CLI Alternatives + +Some of what has been described above is also achievable via the command line. For example, the `--optimize-minimize` flag will include the `TerserPlugin` behind the scenes. The `--define process.env.NODE_ENV="'production'"` will do the same for the `DefinePlugin` instance described above. And, `webpack -p` will automatically invoke both those flags and thus the plugins to be included. + +While these short hand methods are nice, we usually recommend just using the configuration as it's better to understand exactly what is being done for you in both cases. The configuration also gives you more control on fine tuning other options within both plugins. + + +# Code Splitting + +T> This guide extends the examples provided in [Getting Started](/guides/getting-started) and [Output Management](/guides/output-management). Please make sure you are at least familiar with the examples provided in them. + +Code splitting is one of the most compelling features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel. It can be used to achieve smaller bundles and control resource load prioritization which, if used correctly, can have a major impact on load time. + +There are three general approaches to code splitting available: + +- Entry Points: Manually split code using [`entry`](/configuration/entry-context) configuration. +- Prevent Duplication: Use the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) to dedupe and split chunks. +- Dynamic Imports: Split code via inline function calls within modules. + + +## Entry Points + +This is by far the easiest, and most intuitive, way to split code. However, it is more manual and has some pitfalls we will go over. Let's take a look at how we might split another module from the main bundle: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- another-module.js +|- /node_modules +``` + +__another-module.js__ + +``` js +import _ from 'lodash'; + +console.log( + _.join(['Another', 'module', 'loaded!'], ' ') +); +``` + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + mode: 'development', + entry: { + index: './src/index.js', ++ another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +This will yield the following build result: + +``` bash +... + Asset Size Chunks Chunk Names +another.bundle.js 550 KiB another [emitted] another + index.bundle.js 550 KiB index [emitted] index +Entrypoint index = index.bundle.js +Entrypoint another = another.bundle.js +... +``` + +As mentioned there are some pitfalls to this approach: + +- If there are any duplicated modules between entry chunks they will be included in both bundles. +- It isn't as flexible and can't be used to dynamically split code with the core application logic. + +The first of these two points is definitely an issue for our example, as `lodash` is also imported within `./src/index.js` and will thus be duplicated in both bundles. Let's remove this duplication by using the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). + + +## Prevent Duplication + +The [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) allows us to extract common dependencies into an existing entry chunk or an entirely new chunk. Let's use this to de-duplicate the `lodash` dependency from the previous example: + +W> The `CommonsChunkPlugin` has been removed in webpack v4 legato. To learn how chunks are treated in the latest version, check out the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + mode: 'development', + entry: { + index: './src/index.js', + another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ optimization: { ++ splitChunks: { ++ chunks: 'all' ++ } ++ } + }; +``` + +With the [`optimization.splitChunks`](/plugins/split-chunks-plugin/#optimization-splitchunks) configuration option in place, we should now see the duplicate dependency removed from our `index.bundle.js` and `another.bundle.js`. The plugin should notice that we've separated `lodash` out to a separate chunk and remove the dead weight from our main bundle. Let's do an `npm run build` to see if it worked: + +``` bash +... + Asset Size Chunks Chunk Names + another.bundle.js 5.95 KiB another [emitted] another + index.bundle.js 5.89 KiB index [emitted] index +vendors~another~index.bundle.js 547 KiB vendors~another~index [emitted] vendors~another~index +Entrypoint index = vendors~another~index.bundle.js index.bundle.js +Entrypoint another = vendors~another~index.bundle.js another.bundle.js +... +``` + +Here are some other useful plugins and loaders provided by the community for splitting code: + +- [`mini-css-extract-plugin`](/plugins/mini-css-extract-plugin): Useful for splitting CSS out from the main application. +- [`bundle-loader`](/loaders/bundle-loader): Used to split code and lazy load the resulting bundles. +- [`promise-loader`](https://github.com/gaearon/promise-loader): Similar to the `bundle-loader` but uses promises. + + +## Dynamic Imports + +Two similar techniques are supported by webpack when it comes to dynamic code splitting. The first and recommended approach is to use the [`import()` syntax](/api/module-methods#import-) that conforms to the [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) for dynamic imports. The legacy, webpack-specific approach is to use [`require.ensure`](/api/module-methods#require-ensure). Let's try using the first of these two approaches... + +W> `import()` calls use [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +Before we start, let's remove the extra [`entry`](/concepts/entry-points/) and [`optimization.splitChunks`](/plugins/split-chunks-plugin) from our config as they won't be needed for this next demonstration: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + mode: 'development', + entry: { ++ index: './src/index.js' +- index: './src/index.js', +- another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', ++ chunkFilename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- optimization: { +- splitChunks: { +- chunks: 'all' +- } +- } + }; +``` + +Note the use of `chunkFilename`, which determines the name of non-entry chunk files. For more information on `chunkFilename`, see [output documentation](/configuration/output/#output-chunkfilename). We'll also update our project to remove the now unused files: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +- |- another-module.js +|- /node_modules +``` + +Now, instead of statically importing `lodash`, we'll use dynamic importing to separate a chunk: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; +- +- function component() { ++ function getComponent() { +- var element = document.createElement('div'); +- +- // Lodash, now imported by this script +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => { ++ var element = document.createElement('div'); ++ ++ element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ ++ return element; ++ ++ }).catch(error => 'An error occurred while loading the component'); + } + +- document.body.appendChild(component()); ++ getComponent().then(component => { ++ document.body.appendChild(component); ++ }) +``` + +The reason we need `default` is since webpack 4, when importing a CommonJS module, the import will no longer resolve to the value of `module.exports`, it will instead create an artificial namespace object for the CommonJS module, for more information on the reason behind this, read [webpack 4: import() and CommonJs](https://medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655) + +Note the use of `webpackChunkName` in the comment. This will cause our separate bundle to be named `lodash.bundle.js` instead of just `[id].bundle.js`. For more information on `webpackChunkName` and the other available options, see the [`import()` documentation](/api/module-methods#import-). Let's run webpack to see `lodash` separated out to a separate bundle: + +``` bash +... + Asset Size Chunks Chunk Names + index.bundle.js 7.88 KiB index [emitted] index +vendors~lodash.bundle.js 547 KiB vendors~lodash [emitted] vendors~lodash +Entrypoint index = index.bundle.js +... +``` + +As `import()` returns a promise, it can be used with [`async` functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). However, this requires using a pre-processor like Babel and the [Syntax Dynamic Import Babel Plugin](https://babeljs.io/docs/plugins/syntax-dynamic-import/#installation). Here's how it would simplify the code: + +__src/index.js__ + +``` diff +- function getComponent() { ++ async function getComponent() { +- return import(/* webpackChunkName: "lodash" */ 'lodash').then({ default: _ } => { +- var element = document.createElement('div'); +- +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- +- return element; +- +- }).catch(error => 'An error occurred while loading the component'); ++ var element = document.createElement('div'); ++ const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash'); ++ ++ element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ ++ return element; + } + + getComponent().then(component => { + document.body.appendChild(component); + }); +``` + + +## Prefetching/Preloading modules + +webpack 4.6.0+ adds support for prefetching and preloading. + +Using these inline directives while declaring your imports allows webpack to output “Resource Hint” which tells the browser that for: + +- prefetch: resource is probably needed for some navigation in the future +- preload: resource might be needed during the current navigation + +Simple prefetch example can be having a `HomePage` component, which renders a `LoginButton` component which then on demand loads a `LoginModal` component after being clicked. + +__LoginButton.js__ + +```js +//... +import(/* webpackPrefetch: true */ 'LoginModal'); +``` + +This will result in `<link rel="prefetch" href="login-modal-chunk.js">` being appended in the head of the page, which will instruct the browser to prefetch in idle time the `login-modal-chunk.js` file. + +T> webpack will add the prefetch hint once the parent chunk has been loaded. + +Preload directive has a bunch of differences compared to prefetch: + +- A preloaded chunk starts loading in parallel to the parent chunk. A prefetched chunk starts after the parent chunk finishes loading. +- A preloaded chunk has medium priority and is instantly downloaded. A prefetched chunk is downloaded while browser is idle. +- A preloaded chunk should be instantly requested by the parent chunk. A prefetched chunk can be used anytime in the future. +- Browser support is different. + +Simple preload example can be having a `Component` which always depends on a big library that should be in a separate chunk. + +Let's imagine a component `ChartComponent` which needs huge `ChartingLibrary`. It displays a `LoadingIndicator` when rendered and instantly does an on demand import of `ChartingLibrary`: + +__ChartComponent.js__ + +```js +//... +import(/* webpackPreload: true */ 'ChartingLibrary'); +``` + +When a page which uses the `ChartComponent` is requested, the charting-library-chunk is also requested via `<link rel="preload">`. Assuming the page-chunk is smaller and finishes faster, the page will be displayed with a `LoadingIndicator`, until the already requested `charting-library-chunk` finishes. This will give a little load time boost since it only needs one round-trip instead of two. Especially in high-latency environments. + +T> Using webpackPreload incorrectly can actually hurt performance, so be careful when using it. + + +## Bundle Analysis + +Once you start splitting your code, it can be useful to analyze the output to check where modules have ended up. The [official analyze tool](https://github.com/webpack/analyse) is a good place to start. There are some other community-supported options out there as well: + +- [webpack-chart](https://alexkuz.github.io/webpack-chart/): Interactive pie chart for webpack stats. +- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/): Visualize and analyze your bundles to see which modules are taking up space and which might be duplicates. +- [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer): A plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap. +- [webpack bundle optimize helper](https://webpack.jakoblind.no/optimize): This tool will analyze your bundle and give you actionable suggestions on what to improve to reduce your bundle size. + +## Next Steps + +See [Lazy Loading](/guides/lazy-loading) for a more concrete example of how `import()` can be used in a real application and [Caching](/guides/caching) to learn how to split code more effectively. + + +# Lazy Loading + +T> This guide is a small follow-up to [Code Splitting](/guides/code-splitting). If you have not yet read through that guide, please do so now. + +Lazy, or "on demand", loading is a great way to optimize your site or application. This practice essentially involves splitting your code at logical breakpoints, and then loading it once the user has done something that requires, or will require, a new block of code. This speeds up the initial load of the application and lightens its overall weight as some blocks may never even be loaded. + + +## Example + +Let's take the example from [Code Splitting](/guides/code-splitting#dynamic-imports) and tweak it a bit to demonstrate this concept even more. The code there does cause a separate chunk, `lodash.bundle.js`, to be generated and technically "lazy-loads" it as soon as the script is run. The trouble is that no user interaction is required to load the bundle -- meaning that every time the page is loaded, the request will fire. This doesn't help us too much and will impact performance negatively. + +Let's try something different. We'll add an interaction to log some text to the console when the user clicks a button. However, we'll wait to load that code (`print.js`) until the interaction occurs for the first time. To do this we'll go back and rework the [final _Dynamic Imports_ example](/guides/code-splitting#dynamic-imports) from _Code Splitting_ and leave `lodash` in the main chunk. + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- print.js +|- /node_modules +``` + +__src/print.js__ + +``` js +console.log('The print.js module has loaded! See the network tab in dev tools...'); + +export default () => { + console.log('Button Clicked: Here\'s "some text"!'); +}; +``` + +__src/index.js__ + +``` diff ++ import _ from 'lodash'; ++ +- async function getComponent() { ++ function component() { + var element = document.createElement('div'); +- const _ = await import(/* webpackChunkName: "lodash" */ 'lodash'); ++ var button = document.createElement('button'); ++ var br = document.createElement('br'); + ++ button.innerHTML = 'Click me and look at the console!'; + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.appendChild(br); ++ element.appendChild(button); ++ ++ // Note that because a network request is involved, some indication ++ // of loading would need to be shown in a production-level site/app. ++ button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => { ++ var print = module.default; ++ ++ print(); ++ }); + + return element; + } + +- getComponent().then(component => { +- document.body.appendChild(component); +- }); ++ document.body.appendChild(component()); +``` + +W> Note that when using `import()` on ES6 modules you must reference the `.default` property as it's the actual `module` object that will be returned when the promise is resolved. + +Now let's run webpack and check out our new lazy-loading functionality: + +``` bash +... + Asset Size Chunks Chunk Names +print.bundle.js 417 bytes 0 [emitted] print +index.bundle.js 548 kB 1 [emitted] [big] index + index.html 189 bytes [emitted] +... +``` + + +## Frameworks + +Many frameworks and libraries have their own recommendations on how this should be accomplished within their methodologies. Here are a few examples: + +- React: [Code Splitting and Lazy Loading](https://reacttraining.com/react-router/web/guides/code-splitting) +- Vue: [Lazy Load in Vue using Webpack's code splitting](https://alexjoverm.github.io/2017/07/16/Lazy-load-in-Vue-using-Webpack-s-code-splitting/) +- AngularJS: [AngularJS + Webpack = lazyLoad](https://medium.com/@var_bin/angularjs-webpack-lazyload-bb7977f390dd) by [@var_bincom](https://twitter.com/var_bincom) + + +# Caching + +T> The examples in this guide stem from [getting started](/guides/getting-started), [output management](/guides/output-management) and [code splitting](/guides/code-splitting). + +So we're using webpack to bundle our modular application which yields a deployable `/dist` directory. Once the contents of `/dist` have been deployed to a server, clients (typically browsers) will hit that server to grab the site and its assets. The last step can be time consuming, which is why browsers use a technique called [caching](https://searchstorage.techtarget.com/definition/cache). This allows sites to load faster with less unnecessary network traffic, however it can also cause headaches when you need new code to be picked up. + +This guide focuses on the configuration needed to ensure files produced by webpack compilation can remain cached unless their contents has changed. + + +## Output Filenames + +A simple way to ensure the browser picks up changed files is by using `output.filename` [substitutions](/configuration/output#output-filename). The `[hash]` substitution can be used to include a build-specific hash in the filename, however it's even better to use the `[contenthash]` substitution which is the hash of the content of a file, which is different for each asset. + +Let's get our project set up using the example from [getting started](/guides/getting-started) with the `plugins` from [output management](/guides/output-management), so we don't have to deal with maintaining our `index.html` file manually: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +|- /node_modules +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ +- title: 'Output Management' ++ title: 'Caching' + }) + ], + output: { +- filename: 'bundle.js', ++ filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Running our build script, `npm run build`, with this configuration should produce the following output: + +``` bash +... + Asset Size Chunks Chunk Names +main.7e2c49a622975ebd9b7e.js 544 kB 0 [emitted] [big] main + index.html 197 bytes [emitted] +... +``` + +As you can see the bundle's name now reflects its content (via the hash). If we run another build without making any changes, we'd expect that filename to stay the same. However, if we were to run it again, we may find that this is not the case: + +``` bash +... + Asset Size Chunks Chunk Names +main.205199ab45963f6a62ec.js 544 kB 0 [emitted] [big] main + index.html 197 bytes [emitted] +... +``` + +This is because webpack includes certain boilerplate, specifically the runtime and manifest, in the entry chunk. + +W> Output may differ depending on your current webpack version. Newer versions may not have all the same issues with hashing as some older versions, but we still recommend the following steps to be safe. + +## Extracting Boilerplate + +As we learned in [code splitting](/guides/code-splitting), the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) can be used to split modules out into separate bundles. webpack provides an optimization feature which does split out runtime code into a separate chunk(s) according to the options provided, simply use [`optimization.runtimeChunk`](/configuration/optimization/#optimization-runtimechunk) set to `single` for creating one runtime bundle: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, ++ optimization: { ++ runtimeChunk: 'single' ++ } + }; +``` + +Let's run another build to see the extracted `runtime` bundle: + +``` bash +Hash: 82c9c385607b2150fab2 +Version: webpack 4.12.0 +Time: 3027ms + Asset Size Chunks Chunk Names +runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime + main.e81de2cf758ada72f306.js 69.5 KiB 1 [emitted] main + index.html 275 bytes [emitted] +[1] (webpack)/buildin/module.js 497 bytes {1} [built] +[2] (webpack)/buildin/global.js 489 bytes {1} [built] +[3] ./src/index.js 309 bytes {1} [built] + + 1 hidden module +``` + +It's also good practice to extract third-party libraries, such as `lodash` or `react`, to a separate `vendor` chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date. +This can be done by using the [`cacheGroups`](/plugins/split-chunks-plugin/#splitchunks-cachegroups) option of the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) demonstrated in [Example 2 of SplitChunksPlugin](/plugins/split-chunks-plugin/#split-chunks-example-2). Lets add `optimization.splitChunks` with `cacheGroups` with next params and build: + +__webpack.config.js__ + +``` diff + var path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + }), + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, + optimization: { +- runtimeChunk: 'single' ++ runtimeChunk: 'single', ++ splitChunks: { ++ cacheGroups: { ++ vendor: { ++ test: /[\\/]node_modules[\\/]/, ++ name: 'vendors', ++ chunks: 'all' ++ } ++ } ++ } + } + }; +``` + +Let's run another build to see our new `vendor` bundle: + +``` bash +... + Asset Size Chunks Chunk Names +runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime +vendors.a42c3ca0d742766d7a28.js 69.4 KiB 1 [emitted] vendors + main.abf44fedb7d11d4312d7.js 240 bytes 2 [emitted] main + index.html 353 bytes [emitted] +... +``` + +We can now see that our `main` bundle does not contain `vendor` code from `node_modules` directory and is down in size to `240 bytes`! + +## Module Identifiers + +Let's add another module, `print.js`, to our project: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- print.js +|- /node_modules +``` + +__print.js__ + +``` diff ++ export default function print(text) { ++ console.log(text); ++ }; +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import Print from './print'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.onclick = Print.bind(null, 'Hello webpack!'); + + return element; + } + + document.body.appendChild(component()); +``` + +Running another build, we would expect only our `main` bundle's hash to change, however... + +``` bash +... + Asset Size Chunks Chunk Names + vendor.a7561fb0e9a071baadb9.js 541 kB 0 [emitted] [big] vendor + main.b746e3eb72875af2caa9.js 1.22 kB 1 [emitted] main +manifest.1400d5af64fc1b7b3a45.js 5.85 kB 2 [emitted] manifest + index.html 352 bytes [emitted] +... +``` + +... we can see that all three have. This is because each [`module.id`](/api/module-variables#module-id-commonjs-) is incremented based on resolving order by default. Meaning when the order of resolving is changed, the IDs will be changed as well. So, to recap: + +- The `main` bundle changed because of its new content. +- The `vendor` bundle changed because its `module.id` was changed. +- And, the `manifest` bundle changed because it now contains a reference to a new module. + +The first and last are expected -- it's the `vendor` hash we want to fix. Luckily, there are two plugins we can use to resolve this issue. The first is the `NamedModulesPlugin`, which will use the path to the module rather than a numerical identifier. While this plugin is useful during development for more readable output, it does take a bit longer to run. The second option is the [`HashedModuleIdsPlugin`](/plugins/hashed-module-ids-plugin), which is recommended for production builds: + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const webpack = require('webpack'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + }), ++ new webpack.HashedModuleIdsPlugin() + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, + optimization: { + runtimeChunk: 'single', + splitChunks: { + cacheGroups: { + vendor: { + test: /[\\/]node_modules[\\/]/, + name: 'vendors', + chunks: 'all' + } + } + } + } + }; +``` + +Now, despite any new local dependencies, our `vendor` hash should stay consistent between builds: + +``` bash +... + Asset Size Chunks Chunk Names + main.216e852f60c8829c2289.js 340 bytes 0 [emitted] main +vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors +runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime + index.html 353 bytes [emitted] +Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.216e852f60c8829c2289.js +... +``` + +And let's modify our `src/index.js` to temporarily remove that extra dependency: + +__src/index.js__ + +``` diff + import _ from 'lodash'; +- import Print from './print'; ++ // import Print from './print'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- element.onclick = Print.bind(null, 'Hello webpack!'); ++ // element.onclick = Print.bind(null, 'Hello webpack!'); + + return element; + } + + document.body.appendChild(component()); +``` + +And finally run our build again: + +``` bash +... + Asset Size Chunks Chunk Names + main.ad717f2466ce655fff5c.js 274 bytes 0 [emitted] main +vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors +runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime + index.html 353 bytes [emitted] +Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.ad717f2466ce655fff5c.js +... +``` + +We can see that both builds yielded `55e79e5927a639d21a1b` in the `vendor` bundle's filename. + + +## Conclusion + +Caching gets messy. Plain and simple. However the walk-through above should give you a running start to deploying consistent, cacheable assets. See the _Further Reading_ section below to learn more. + + +# Authoring Libraries + +Aside from applications, webpack can also be used to bundle JavaScript libraries. The following guide is meant for library authors looking to streamline their bundling strategy. + + +## Authoring a Library + +Let's assume that you are writing a small library ,`webpack-numbers`, that allows users to convert the numbers 1 through 5 from their numeric representation to a textual one and vice-versa, e.g. 2 to 'two'. + +The basic project structure may look like this: + +__project__ + +``` diff ++ |- webpack.config.js ++ |- package.json ++ |- /src ++ |- index.js ++ |- ref.json +``` + +Initialize npm, install webpack and lodash: + +``` bash +npm init -y +npm install --save-dev webpack lodash +``` + +__src/ref.json__ + +```json +[ + { + "num": 1, + "word": "One" + }, + { + "num": 2, + "word": "Two" + }, + { + "num": 3, + "word": "Three" + }, + { + "num": 4, + "word": "Four" + }, + { + "num": 5, + "word": "Five" + }, + { + "num": 0, + "word": "Zero" + } +] +``` + +__src/index.js__ + +``` js +import _ from 'lodash'; +import numRef from './ref.json'; + +export function numToWord(num) { + return _.reduce(numRef, (accum, ref) => { + return ref.num === num ? ref.word : accum; + }, ''); +} + +export function wordToNum(word) { + return _.reduce(numRef, (accum, ref) => { + return ref.word === word && word.toLowerCase() ? ref.num : accum; + }, -1); +} +``` + +The usage specification for the library use will be as follows: + +- __ES2015 module import:__ + +``` js +import * as webpackNumbers from 'webpack-numbers'; +// ... +webpackNumbers.wordToNum('Two'); +``` + +- __CommonJS module require:__ + +``` js +var webpackNumbers = require('webpack-numbers'); +// ... +webpackNumbers.wordToNum('Two'); +``` + +- __AMD module require:__ + +``` js +require(['webpackNumbers'], function ( webpackNumbers) { + // ... + webpackNumbers.wordToNum('Two'); +}); +``` + +The consumer also can use the library by loading it via a script tag: + +``` html +<!doctype html> +<html> + ... + <script src="https://unpkg.com/webpack-numbers"></script> + <script> + // ... + // Global variable + webpackNumbers.wordToNum('Five') + // Property in the window object + window.webpackNumbers.wordToNum('Five') + // ... + </script> +</html> +``` + +Note that we can also configure it to expose the library in the following ways: + +- Property in the global object, for node. +- Property in the `this` object. + +For full library configuration and code please refer to [webpack-library-example](https://github.com/kalcifer/webpack-library-example). + + +## Base Configuration + +Now let's bundle this library in a way that will achieve the following goals: + +- Using `externals` to avoid bundling `lodash`, so the consumer is required to load it. +- Setting the library name as `webpack-numbers`. +- Exposing the library as a variable called `webpackNumbers`. +- Being able to access the library inside Node.js. + +Also, the consumer should be able to access the library the following ways: + +- ES2015 module. i.e. `import webpackNumbers from 'webpack-numbers'`. +- CommonJS module. i.e. `require('webpack-numbers')`. +- Global variable when included through `script` tag. + +We can start with this basic webpack configuration: + +__webpack.config.js__ + +``` js +var path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js' + } +}; +``` + + +## Externalize Lodash + +Now, if you run `webpack`, you will find that a largish bundle is created. If you inspect the file, you'll see that lodash has been bundled along with your code. In this case, we'd prefer to treat `lodash` as a `peerDependency`. Meaning that the consumer should already have `lodash` installed. Hence you would want to give up control of this external library to the consumer of your library. + +This can be done using the `externals` configuration: + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js' +- } ++ }, ++ externals: { ++ lodash: { ++ commonjs: 'lodash', ++ commonjs2: 'lodash', ++ amd: 'lodash', ++ root: '_' ++ } ++ } + }; +``` + +This means that your library expects a dependency named `lodash` to be available in the consumer's environment. + +T> Note that if you only plan on using your library as a dependency in another webpack bundle, you may specify `externals` as an array. + + +## External Limitations + +For libraries that use several files from a dependency: + +``` js +import A from 'library/one'; +import B from 'library/two'; + +// ... +``` + +You won't be able to exclude them from bundle by specifying `library` in the externals. You'll either need to exclude them one by one or by using a regular expression. + +``` js +module.exports = { + //... + externals: [ + 'library/one', + 'library/two', + // Everything that starts with "library/" + /^library\/.+$/ + ] +}; +``` + + +## Expose the Library + +For widespread use of the library, we would like it to be compatible in different environments, i.e. CommonJS, AMD, Node.js and as a global variable. To make your library available for consumption, add the `library` property inside `output`: + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), +- filename: 'webpack-numbers.js' ++ filename: 'webpack-numbers.js', ++ library: 'webpackNumbers' + }, + externals: { + lodash: { + commonjs: 'lodash', + commonjs2: 'lodash', + amd: 'lodash', + root: '_' + } + } + }; +``` + +T> Note that the `library` setup is tied to the `entry` configuration. For most libraries, specifying a single entry point is sufficient. While [multi-part libraries](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) are possible, it is simpler to expose partial exports through an [index script](https://stackoverflow.com/questions/34072598/es6-exporting-importing-in-index-file) that serves as a single entry point. Using an `array` as an `entry` point for a library is __not recommended__. + +This exposes your library bundle available as a global variable named `webpackNumbers` when imported. To make the library compatible with other environments, add `libraryTarget` property to the config. This will add the different options about how the library can be exposed. + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js', +- library: 'webpackNumbers' ++ library: 'webpackNumbers', ++ libraryTarget: 'umd' + }, + externals: { + lodash: { + commonjs: 'lodash', + commonjs2: 'lodash', + amd: 'lodash', + root: '_' + } + } + }; +``` + +You can expose the library in the following ways: + +- Variable: as a global variable made available by a `script` tag (`libraryTarget:'var'`). +- This: available through the `this` object (`libraryTarget:'this'`). +- Window: available trough the `window` object, in the browser (`libraryTarget:'window'`). +- UMD: available after AMD or CommonJS `require` (`libraryTarget:'umd'`). + +If `library` is set and `libraryTarget` is not, `libraryTarget` defaults to `var` as specified in the [output configuration documentation](/configuration/output). See [`output.libraryTarget`](/configuration/output#output-librarytarget) there for a detailed list of all available options. + +W> With webpack 3.5.5, using `libraryTarget: { root:'_' }` doesn't work properly (as stated in [issue 4824](https://github.com/webpack/webpack/issues/4824)). However, you can set `libraryTarget: { var: '_' }` to expect the library as a global variable. + + +### Final Steps + +Optimize your output for production by following the steps in the [production guide](/guides/production). Let's also add the path to your generated bundle as the package's `main` field in with our `package.json` + +__package.json__ + +``` json +{ + ... + "main": "dist/webpack-numbers.js", + ... +} +``` + +Or, to add as standard module as per [this guide](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage): + +``` json +{ + ... + "module": "src/index.js", + ... +} +``` + +The key `main` refers to the [standard from `package.json`](https://docs.npmjs.com/files/package.json#main), and `module` to [a](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md) [proposal](https://github.com/rollup/rollup/wiki/pkg.module) to allow the JavaScript ecosystem upgrade to use ES2015 modules without breaking backwards compatibility. + +W> The `module` property should point to a script that utilizes ES2015 module syntax but no other syntax features that aren't yet supported by browsers or node. This enables webpack to parse the module syntax itself, allowing for lighter bundles via [tree shaking](https://webpack.js.org/guides/tree-shaking/) if users are only consuming certain parts of the library. + +Now you can [publish it as an npm package](https://docs.npmjs.com/getting-started/publishing-npm-packages) and find it at [unpkg.com](https://unpkg.com/#/) to distribute it to your users. + +T> To expose stylesheets associated with your library, the [`ExtractTextPlugin`](/plugins/extract-text-webpack-plugin) should be used. Users can then consume and load these as they would any other stylesheet. + + +# Shimming + +The `webpack` compiler can understand modules written as ES2015 modules, CommonJS or AMD. However, some third party libraries may expect global dependencies (e.g. `$` for `jQuery`). The libraries might also create globals which need to be exported. These "broken modules" are one instance where _shimming_ comes into play. + +W> __We don't recommend using globals!__ The whole concept behind webpack is to allow more modular front-end development. This means writing isolated modules that are well contained and do not rely on hidden dependencies (e.g. globals). Please use these features only when necessary. + +Another instance where _shimming_ can be useful is when you want to [polyfill](https://en.wikipedia.org/wiki/Polyfill) browser functionality to support more users. In this case, you may only want to deliver those polyfills to the browsers that need patching (i.e. load them on demand). + +The following article will walk through both of these use cases. + +T> For simplicity, this guide stems from the examples in [Getting Started](/guides/getting-started). Please make sure you are familiar with the setup there before moving on. + + +## Shimming Globals + +Let's start with the first use case of shimming global variables. Before we do anything let's take another look at our project: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +|- /node_modules +``` + +Remember that `lodash` package we were using? For demonstration purposes, let's say we wanted to instead provide this as a global throughout our application. To do this, we can use the `ProvidePlugin`. + +The [`ProvidePlugin`](/plugins/provide-plugin) makes a package available as a variable in every module compiled through webpack. If webpack sees that variable used, it will include the given package in the final bundle. Let's go ahead by removing the `import` statement for `lodash` and instead providing it via the plugin: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; +- + function component() { + var element = document.createElement('div'); + +- // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') +- } ++ }, ++ plugins: [ ++ new webpack.ProvidePlugin({ ++ _: 'lodash' ++ }) ++ ] + }; +``` + +What we've essentially done here is tell webpack... + +> If you encounter at least one instance of the variable `_`, include the `lodash` package and provide it to the modules that need it. + +If we run a build, we should still see the same output: + +``` bash +... + Asset Size Chunks Chunk Names +bundle.js 544 kB 0 [emitted] [big] main +... +``` + +We can also use the `ProvidePlugin` to expose a single export of a module by configuring it with an "array path" (e.g. `[module, child, ...children?]`). So let's imagine we only wanted to provide the `join` method from `lodash` wherever it's invoked: + +__src/index.js__ + +``` diff + function component() { + var element = document.createElement('div'); + +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + plugins: [ + new webpack.ProvidePlugin({ +- _: 'lodash' ++ join: ['lodash', 'join'] + }) + ] + }; +``` + +This would go nicely with [Tree Shaking](/guides/tree-shaking) as the rest of the `lodash` library should get dropped. + + +## Granular Shimming + +Some legacy modules rely on `this` being the `window` object. Let's update our `index.js` so this is the case: + +``` diff + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); ++ ++ // Assume we are in the context of `window` ++ this.alert('Hmmm, this probably isn\'t a great idea...') + + return element; + } + + document.body.appendChild(component()); +``` + +This becomes a problem when the module is executed in a CommonJS context where `this` is equal to `module.exports`. In this case you can override `this` using the [`imports-loader`](/loaders/imports-loader/): + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ module: { ++ rules: [ ++ { ++ test: require.resolve('index.js'), ++ use: 'imports-loader?this=>window' ++ } ++ ] ++ }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + + +## Global Exports + +Let's say a library creates a global variable that it expects its consumers to use. We can add a small module to our setup to demonstrate this: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js ++ |- globals.js + |- /node_modules +``` + +__src/globals.js__ + +``` js +var file = 'blah.txt'; +var helpers = { + test: function() { console.log('test something'); }, + parse: function() { console.log('parse something'); } +}; +``` + +Now, while you'd likely never do this in your own source code, you may encounter a dated library you'd like to use that contains similar code to what's shown above. In this case, we can use [`exports-loader`](/loaders/exports-loader/), to export that global variable as a normal module export. For instance, in order to export `file` as `file` and `helpers.parse` as `parse`: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: require.resolve('index.js'), + use: 'imports-loader?this=>window' +- } ++ }, ++ { ++ test: require.resolve('globals.js'), ++ use: 'exports-loader?file,parse=helpers.parse' ++ } + ] + }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + +Now from within our entry script (i.e. `src/index.js`), we could `import { file, parse } from './globals.js';` and all should work smoothly. + + +## Loading Polyfills + +Almost everything we've discussed thus far has been in relation to handling legacy packages. Let's move on to our second topic: __polyfills__. + +There's a lot of ways to load polyfills. For example, to include the [`babel-polyfill`](https://babeljs.io/docs/usage/polyfill/) we might simply: + +``` bash +npm install --save babel-polyfill +``` + +and `import` it so as to include it in our main bundle: + +__src/index.js__ + +``` diff ++ import 'babel-polyfill'; ++ + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +T> Note that we aren't binding the `import` to a variable. This is because polyfills simply run on their own, prior to the rest of the code base, allowing us to then assume certain native functionality exists. + +Now while this is one approach, __including polyfills in the main bundle is not recommended__ because this penalizes modern browsers users by making them download a bigger file with unneeded scripts. + +Let's move our `import` to a new file and add the [`whatwg-fetch`](https://github.com/github/fetch) polyfill: + +``` bash +npm install --save whatwg-fetch +``` + +__src/index.js__ + +``` diff +- import 'babel-polyfill'; +- + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js + |- globals.js ++ |- polyfills.js + |- /node_modules +``` + +__src/polyfills.js__ + +```javascript +import 'babel-polyfill'; +import 'whatwg-fetch'; +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { +- entry: './src/index.js', ++ entry: { ++ polyfills: './src/polyfills.js', ++ index: './src/index.js' ++ }, + output: { +- filename: 'bundle.js', ++ filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: require.resolve('index.js'), + use: 'imports-loader?this=>window' + }, + { + test: require.resolve('globals.js'), + use: 'exports-loader?file,parse=helpers.parse' + } + ] + }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + +With that in place, we can add the logic to conditionally load our new `polyfills.bundle.js` file. How you make this decision depends on the technologies and browsers you need to support. We'll just do some simple testing to determine whether our polyfills are needed: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> + <title>Getting Started</title> ++ <script> ++ var modernBrowser = ( ++ 'fetch' in window && ++ 'assign' in Object ++ ); ++ ++ if ( !modernBrowser ) { ++ var scriptElement = document.createElement('script'); ++ ++ scriptElement.async = false; ++ scriptElement.src = '/polyfills.bundle.js'; ++ document.head.appendChild(scriptElement); ++ } ++ </script> + </head> + <body> + <script src="index.bundle.js"></script> + </body> + </html> +``` + +Now we can `fetch` some data within our entry script: + +__src/index.js__ + +``` diff + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); ++ ++ fetch('https://jsonplaceholder.typicode.com/users') ++ .then(response => response.json()) ++ .then(json => { ++ console.log('We retrieved some data! AND we\'re confident it will work on a variety of browser distributions.') ++ console.log(json) ++ }) ++ .catch(error => console.error('Something went wrong when fetching this data: ', error)) +``` + +If we run our build, another `polyfills.bundle.js` file will be emitted and everything should still run smoothly in the browser. Note that this set up could likely be improved upon but it should give you a good idea of how you can provide polyfills only to the users that actually need them. + + +## Further Optimizations + +The `babel-preset-env` package uses [browserslist](https://github.com/browserslist/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the [`useBuiltIns`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins) option, `false` by default, which converts your global `babel-polyfill` import to a more granular feature by feature `import` pattern: + +``` js +import 'core-js/modules/es7.string.pad-start'; +import 'core-js/modules/es7.string.pad-end'; +import 'core-js/modules/web.timers'; +import 'core-js/modules/web.immediate'; +import 'core-js/modules/web.dom.iterable'; +``` + +See [the repository](https://github.com/babel/babel-preset-env) for more information. + + +## Node Built-Ins + +Node built-ins, like `process`, can be polyfilled right directly from your configuration file without the use of any special loaders or plugins. See the [node configuration page](/configuration/node) for more information and examples. + + +## Other Utilities + +There are a few other tools that can help when dealing with legacy modules. + +The [`script-loader`](/loaders/script-loader/) evaluates code in the global context, similar to inclusion via a `script` tag. In this mode, every normal library should work. `require`, `module`, etc. are undefined. + +W> When using the `script-loader`, the module is added as a string to the bundle. It is not minimized by `webpack`, so use a minimized version. There is also no `devtool` support for libraries added by this loader. + +When there is no AMD/CommonJS version of the module and you want to include the `dist`, you can flag this module in [`noParse`](/configuration/module/#module-noparse). This will cause webpack to include the module without parsing it or resolving `require()` and `import` statements. This practice is also used to improve the build performance. + +W> Any feature requiring the AST, like the `ProvidePlugin`, will not work. + +Lastly, there are some modules that support multiple [module styles](/concepts/modules); e.g. a combination of AMD, CommonJS, and legacy. In most of these cases, they first check for `define` and then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by setting `define=>false` via the [`imports-loader`](/loaders/imports-loader/). + + +# Progressive Web Application + +T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. + +Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications. There are many things that can contribute to that. Of these, the most significant is the ability for an app to be able to function when __offline__. This is achieved through the use of a web technology called [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers/). + +This section will focus on adding an offline experience to our app. We'll achieve this using a Google project called [Workbox](https://github.com/GoogleChrome/workbox) which provides tools that help make offline support for web apps easier to setup. + + +## We Don't Work Offline Now + +So far, we've been viewing the output by going directly to the local file system. Typically though, a real user accesses a web app over a network; their browser talking to a __server__ which will serve up the required assets (e.g. `.html`, `.js`, and `.css` files). + +So let's test what the current experience is like using a simple server. Let's use the [http-server](https://www.npmjs.com/package/http-server) package: `npm install http-server --save-dev`. We'll also amend the `scripts` section of our `package.json` to add in a `start` script: + +__package.json__ + +``` diff +{ + ... + "scripts": { +- "build": "webpack" ++ "build": "webpack", ++ "start": "http-server dist" + }, + ... +} +``` + +If you haven't previously done so, run the command `npm run build` to build your project. Then run the command `npm start`. This should produce the following output: + +``` bash +> http-server dist + +Starting up http-server, serving dist +Available on: + http://xx.x.x.x:8080 + http://127.0.0.1:8080 + http://xxx.xxx.x.x:8080 +Hit CTRL-C to stop the server +``` + +If you open your browser to `http://localhost:8080` (i.e. `http://127.0.0.1`) you should see your webpack application being served from the `dist` directory. If you stop the server and refresh, the webpack application is no longer available. + +This is what we aim to change. Once we reach the end of this module we should be able to stop the server, hit refresh and still see our application. + + +## Adding Workbox + +Let's add the Workbox webpack plugin and adjust the `webpack.config.js` file: + +``` bash +npm install workbox-webpack-plugin --save-dev +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const WorkboxPlugin = require('workbox-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ +- title: 'Output Management' ++ title: 'Progressive Web Application' +- }) ++ }), ++ new WorkboxPlugin.GenerateSW({ ++ // these options encourage the ServiceWorkers to get in there fast ++ // and not allow any straggling "old" SWs to hang around ++ clientsClaim: true, ++ skipWaiting: true ++ }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +With that in place, let's see what happens when we do an `npm run build`: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 545 kB 0, 1 [emitted] [big] app + print.bundle.js 2.74 kB 1 [emitted] print + index.html 254 bytes [emitted] +precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 268 bytes [emitted] + service-worker.js 1 kB [emitted] +... +``` + +As you can see, we now have 2 extra files being generated; `service-worker.js` and the more verbose `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js`. `service-worker.js` is the Service Worker file and `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js` is a file that `service-worker.js` requires so it can run. Your own generated files will likely be different; but you should have an `service-worker.js` file there. + +So we're now at the happy point of having produced a Service Worker. What's next? + + +## Registering Our Service Worker + +Let's allow our Service Worker to come out and play by registering it. We'll do that by adding the registration code below: + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + ++ if ('serviceWorker' in navigator) { ++ window.addEventListener('load', () => { ++ navigator.serviceWorker.register('/service-worker.js').then(registration => { ++ console.log('SW registered: ', registration); ++ }).catch(registrationError => { ++ console.log('SW registration failed: ', registrationError); ++ }); ++ }); ++ } +``` + +Once more `npm run build` to build a version of the app including the registration code. Then serve it with `npm start`. Navigate to `http://localhost:8080` and take a look at the console. Somewhere in there you should see: + +``` bash +SW registered +``` + +Now to test it. Stop your server and refresh your page. If your browser supports Service Workers then you should still be looking at your application. However, it has been served up by your Service Worker and __not__ by the server. + + +## Conclusion + +You have built an offline app using the Workbox project. You've started the journey of turning your web app into a PWA. You may now want to think about taking things further. A good resource to help you with that can be found [here](https://developers.google.com/web/progressive-web-apps/). + + +# TypeScript + +T> This guide stems from the [_Getting Started_](/guides/getting-started/) guide. + +[TypeScript](https://www.typescriptlang.org) is a typed superset of JavaScript that compiles to plain JavaScript. In this guide we will learn how to integrate TypeScript with webpack. + + +## Basic Setup + +First install the TypeScript compiler and loader by running: + +``` bash +npm install --save-dev typescript ts-loader +``` + +Now we'll modify the directory structure & the configuration files: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- tsconfig.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src + |- index.js ++ |- index.ts + |- /node_modules +``` + +__tsconfig.json__ + +Let's set up a simple configuration to support JSX and compile TypeScript down to ES5... + +``` json +{ + "compilerOptions": { + "outDir": "./dist/", + "noImplicitAny": true, + "module": "es6", + "target": "es5", + "jsx": "react", + "allowJs": true + } +} +``` + +See [TypeScript's documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) to learn more about `tsconfig.json` configuration options. + +To learn more about webpack configuration, see the [configuration concepts](/concepts/configuration/). + +Now let's configure webpack to handle TypeScript: + +__webpack.config.js__ + +``` js +const path = require('path'); + +module.exports = { + entry: './src/index.ts', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [ '.tsx', '.ts', '.js' ] + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +This will direct webpack to _enter_ through `./index.ts`, _load_ all `.ts` and `.tsx` files through the `ts-loader`, and _output_ a `bundle.js` file in our current directory. + + +## Loader + +[`ts-loader`](https://github.com/TypeStrong/ts-loader) + +We use `ts-loader` in this guide as it makes enabling additional webpack features, such as importing other web assets, a bit easier. + + +## Source Maps + +To learn more about source maps, see the [development guide](/guides/development). + +To enable source maps, we must configure TypeScript to output inline source maps to our compiled JavaScript files. The following line must be added to our TypeScript configuration: + +__tsconfig.json__ + +``` diff + { + "compilerOptions": { + "outDir": "./dist/", ++ "sourceMap": true, + "noImplicitAny": true, + "module": "commonjs", + "target": "es5", + "jsx": "react", + "allowJs": true + } + } +``` + +Now we need to tell webpack to extract these source maps and include in our final bundle: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.ts', ++ devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [ '.tsx', '.ts', '.js' ] + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +See the [devtool documentation](/configuration/devtool/) for more information. + + +## Using Third Party Libraries + +When installing third party libraries from npm, it is important to remember to install the typing definition for that library. These definitions can be found at [TypeSearch](http://microsoft.github.io/TypeSearch/). + +For example if we want to install lodash we can run the following command to get the typings for it: + +``` bash +npm install --save-dev @types/lodash +``` + +For more information see [this blog post](https://blogs.msdn.microsoft.com/typescript/2016/06/15/the-future-of-declaration-files/). + + +## Importing Other Assets + +To use non-code assets with TypeScript, we need to defer the type for these imports. This requires a `custom.d.ts` file which signifies custom definitions for TypeScript in our project. Let's set up a declaration for `.svg` files: + +__custom.d.ts__ + +```typescript +declare module "*.svg" { + const content: any; + export default content; +} +``` + +Here we declare a new module for SVGs by specifying any import that ends in `.svg` and defining the module's `content` as `any`. We could be more explicit about it being a url by defining the type as string. The same concept applies to other assets including CSS, SCSS, JSON and more. + + +## Build Performance + +W> This may degrade build performance. + +See the [Build Performance](/guides/build-performance/) guide on build tooling. + + +# Environment Variables + +To disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production) you may use environment variables. + +The webpack command line [environment option](/api/cli/#environment-options) `--env` allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your `webpack.config.js`. For example, `--env.production` or `--env.NODE_ENV=local` (`NODE_ENV` is conventionally used to define the environment type, see [here](https://dzone.com/articles/what-you-should-know-about-node-env).) + +```bash +webpack --env.NODE_ENV=local --env.production --progress +``` + +T> Setting up your `env` variable without assignment, `--env.production` sets `--env.production` to `true` by default. There are also other syntaxes that you can use. See the [webpack CLI](/api/cli/#environment-options) documentation for more information. + +There is one change that you will have to make to your webpack config. Typically, `module.exports` points to the configuration object. To use the `env` variable, you must convert `module.exports` to a function: + +__webpack.config.js__ + +``` js +const path = require('path'); + +module.exports = env => { + // Use env.<YOUR VARIABLE> here: + console.log('NODE_ENV: ', env.NODE_ENV); // 'local' + console.log('Production: ', env.production); // true + + return { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +}; +``` + + +# Build Performance + +This guide contains some useful tips for improving build/compilation performance. + +--- + +## General + +The following best practices should help, whether you're running build scripts in [development](/guides/development) or [production](/guides/production). + + +### Stay Up to Date + +Use the latest webpack version. We are always making performance improvements. The latest stable version of webpack is: + +[](https://github.com/webpack/webpack/releases) + +Staying up-to-date with __Node.js__ can also help with performance. On top of this, keeping your package manager (e.g. `npm` or `yarn`) up-to-date can also help. Newer versions create more efficient module trees and increase resolving speed. + + +### Loaders + +Apply loaders to the minimal number of modules necessary. Instead of: + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + loader: 'babel-loader' + } + ] + } +}; +``` + +Use the `include` field to only apply the loader modules that actually need to be transformed by it: + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + include: path.resolve(__dirname, 'src'), + loader: 'babel-loader' + } + ] + } +}; +``` + + +### Bootstrap + +Each additional loader/plugin has a bootup time. Try to use as few tools as possible. + + +### Resolving + +The following steps can increase resolving speed: + +- Minimize the number of items in `resolve.modules`, `resolve.extensions`, `resolve.mainFiles`, `resolve.descriptionFiles`, as they increase the number of filesystem calls. +- Set `resolve.symlinks: false` if you don't use symlinks (e.g. `npm link` or `yarn link`). +- Set `resolve.cacheWithContext: false` if you use custom resolving plugins, that are not context specific. + + +### Dlls + +Use the `DllPlugin` to move code that is changed less often into a separate compilation. This will improve the application's compilation speed, although it does increase complexity of the build process. + + +### Smaller = Faster + +Decrease the total size of the compilation to increase build performance. Try to keep chunks small. + +- Use fewer/smaller libraries. +- Use the `CommonsChunkPlugin` in Multi-Page Applications. +- Use the `CommonsChunkPlugin` in `async` mode in Multi-Page Applications. +- Remove unused code. +- Only compile the part of the code you are currently developing on. + + +### Worker Pool + +The `thread-loader` can be used to offload expensive loaders to a worker pool. + +W> Don't use too many workers, as there is a boot overhead for the Node.js runtime and the loader. Minimize the module transfers between worker and main process. IPC is expensive. + + +### Persistent cache + +Enable persistent caching with the `cache-loader`. Clear cache directory on `"postinstall"` in `package.json`. + + +### Custom plugins/loaders + +Profile them to not introduce a performance problem here. + +--- + + +## Development + +The following steps are especially useful in _development_. + + +### Incremental Builds + +Use webpack's watch mode. Don't use other tools to watch your files and invoke webpack. The built-in watch mode will keep track of timestamps and passes this information to the compilation for cache invalidation. + +In some setups, watching falls back to polling mode. With many watched files, this can cause a lot of CPU load. In these cases, you can increase the polling interval with `watchOptions.poll`. + + +### Compile in Memory + +The following utilities improve performance by compiling and serving assets in memory rather than writing to disk: + +- `webpack-dev-server` +- `webpack-hot-middleware` +- `webpack-dev-middleware` + +### stats.toJson speed + +webpack 4 outputs a large amount of data with its `stats.toJson()` by default. Avoid retrieving portions of the `stats` object unless necessary in the incremental step. `webpack-dev-server` after v3.1.3 contained a substantial performance fix to minimize the amount of data retrieved from the `stats` object per incremental build step. + +### Devtool + +Be aware of the performance differences of the different `devtool` settings. + +- `"eval"` has the best performance, but doesn't assist you for transpiled code. +- The `cheap-source-map` variants are more performant, if you can live with the slightly worse mapping quality. +- Use a `eval-source-map` variant for incremental builds. + +=> In most cases, `cheap-module-eval-source-map` is the best option. + + +### Avoid Production Specific Tooling + +Certain utilities, plugins, and loaders only make sense when building for production. For example, it usually doesn't make sense to minify and mangle your code with the `TerserPlugin` while in development. These tools should typically be excluded in development: + +- `TerserPlugin` +- `ExtractTextPlugin` +- `[hash]`/`[chunkhash]` +- `AggressiveSplittingPlugin` +- `AggressiveMergingPlugin` +- `ModuleConcatenationPlugin` + + +### Minimal Entry Chunk + +webpack only emits updated chunks to the filesystem. For some configuration options, (HMR, `[name]`/`[chunkhash]` in `output.chunkFilename`, `[hash]`) the entry chunk is invalidated in addition to the changed chunks. + +Make sure the entry chunk is cheap to emit by keeping it small. The following code block extracts a chunk containing only the runtime with _all other chunks as children_: + +```js +new CommonsChunkPlugin({ + name: 'manifest', + minChunks: Infinity +}); +``` + +### Avoid Extra Optimization Steps + +webpack does extra algorithmic work to optimize the output for size and load performance. These optimizations are performant for smaller codebases, but can be costly in larger ones: + +```js +module.exports = { + // ... + optimization: { + removeAvailableModules: false, + removeEmptyChunks: false, + splitChunks: false, + } +}; +``` + +### Output Without Path Info + +webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Turn this off in the `options.output.pathinfo` setting: + +```js +module.exports = { + // ... + output: { + pathinfo: false + } +}; +``` + +### Node.js Version + +There has been a [performance regression](https://github.com/nodejs/node/issues/19769) in the latest stable versions of Node.js and its ES2015 `Map` and `Set` implementations. A fix has been merged into master, but a release has yet to be made. In the meantime, to get the most out of incremental build speeds, try to stick with version 8.9.x (the problem exists between 8.9.10 - 9.11.1). webpack has moved to using those ES2015 data structures liberally, and it will improve the initial build times as well. + +### TypeScript Loader + +Recently, `ts-loader` has started to consume the internal TypeScript watch mode APIs which dramatically decreases the number of modules to be rebuilt on each iteration. This `experimentalWatchApi` shares the same logic as the normal TypeScript watch mode itself and is quite stable for development use. Turn on `transpileOnly`, as well, for even faster incremental builds. + +```js +module.exports = { + // ... + test: /\.tsx?$/, + use: [ + { + loader: 'ts-loader', + options: { + transpileOnly: true, + experimentalWatchApi: true, + }, + }, + ], +}; +``` + +Note: the `ts-loader` documentation suggests the use of `cache-loader`, but this actually slows the incremental builds down with disk writes. + +To gain typechecking again, use the [`ForkTsCheckerWebpackPlugin`](https://www.npmjs.com/package/fork-ts-checker-webpack-plugin). + +There is a [full example](https://github.com/TypeStrong/ts-loader/tree/master/examples/fast-incremental-builds) on the ts-loader github repository. + +--- + + +## Production + +The following steps are especially useful in _production_. + +W> __Don't sacrifice the quality of your application for small performance gains!__ Keep in mind that optimization quality is, in most cases, more important than build performance. + + +### Multiple Compilations + +When using multiple compilations, the following tools can help: + +- [`parallel-webpack`](https://github.com/trivago/parallel-webpack): It allows for compilation in a worker pool. +- `cache-loader`: The cache can be shared between multiple compilations. + + +### Source Maps + +Source maps are really expensive. Do you really need them? + +--- + + +## Specific Tooling Issues + +The following tools have certain problems that can degrade build performance: + + +### Babel + +- Minimize the number of preset/plugins + + +### TypeScript + +- Use the `fork-ts-checker-webpack-plugin` for typechecking in a separate process. +- Configure loaders to skip typechecking. +- Use the `ts-loader` in `happyPackMode: true` / `transpileOnly: true`. + + +### Sass + +- `node-sass` has a bug which blocks threads from the Node.js thread pool. When using it with the `thread-loader` set `workerParallelJobs: 2`. + + +# Content Security Policies + +Webpack is capable of adding `nonce` to all scripts that it loads. To activate the feature set a `__webpack_nonce__` variable needs to be included in your entry script. A unique hash based nonce should be generated and provided for each unique page view this is why `__webpack_nonce__` is specified in the entry file and not in the configuration. Please note that `nonce` should always be a base64-encoded string. + + +## Examples + +In the entry file: + +``` js +// ... +__webpack_nonce__ = 'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM='; +// ... +``` + + +## Enabling CSP + +Please note that CSPs are not enabled by default. A corresponding header `Content-Security-Policy` or meta tag `<meta http-equiv="Content-Security-Policy" ...>` needs to be sent with the document to instruct the browser to enable the CSP. Here's an example of what a CSP header including a CDN white-listed URL might look like: + +``` http +Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; +``` + +For more information on CSP and `nonce` attribute, please refer to __Further Reading__ section at the bottom of this page. + + +# Development - Vagrant + +If you have a more advanced project and use [Vagrant](https://www.vagrantup.com/) to run your development environment in a Virtual Machine, you'll often want to also run webpack in the VM. + +## Configuring the Project + +To start, make sure that the `Vagrantfile` has a static IP; + +```ruby +Vagrant.configure("2") do |config| + config.vm.network :private_network, ip: "10.10.10.61" +end +``` + +Next, install webpack and webpack-dev-server in your project; + +```bash +npm install --save-dev webpack webpack-dev-server +``` + +Make sure to have a `webpack.config.js` file. If you haven't already, use this as a minimal example to get started: + +```js +module.exports = { + context: __dirname, + entry: './app.js' +}; +``` + +And create a `index.html` file. The script tag should point to your bundle. If `output.filename` is not specified in the config, this will be `bundle.js`. + +```html +<!doctype html> +<html> + <head> + <script src="/bundle.js" charset="utf-8"></script> + </head> + <body> + <h2>Heey!</h2> + </body> +</html> +``` + +Note that you also need to create an `app.js` file. + +## Running the Server + +Now, let's run the server: + +```bash +webpack-dev-server --host 0.0.0.0 --public 10.10.10.61:8080 --watch-poll +``` + +By default the server will only be accessible from localhost. We'll be accessing it from our host PC, so we need to change `--host` to allow this. + +webpack-dev-server will include a script in your bundle that connects to a WebSocket to reload when a change in any of your files occurs. +The `--public` flag makes sure the script knows where to look for the WebSocket. The server will use port `8080` by default, so we should also specify that here. + +`--watch-poll` makes sure that webpack can detect changes in your files. By default webpack listens to events triggered by the filesystem, but VirtualBox has many problems with this. + +The server should be accessible on `http://10.10.10.61:8080` now. If you make a change in `app.js`, it should live reload. + +## Advanced Usage with nginx + +To mimic a more production-like environment, it is also possible to proxy the webpack-dev-server with nginx. + +In your nginx config file, add the following: + +```nginx +server { + location / { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + error_page 502 @start-webpack-dev-server; + } + + location @start-webpack-dev-server { + default_type text/plain; + return 502 "Please start the webpack-dev-server first."; + } +} +``` + +The `proxy_set_header` lines are important, because they allow the WebSockets to work correctly. + +The command to start webpack-dev-server can then be changed to this: + +```bash +webpack-dev-server --public 10.10.10.61 --watch-poll +``` + +This makes the server only accessible on `127.0.0.1`, which is fine, because nginx takes care of making it available on your host PC. + +## Conclusion + +We made the Vagrant box accessible from a static IP, and then made webpack-dev-server publicly accessible so it is reachable from a browser. We then tackled a common problem that VirtualBox doesn't send out filesystem events, causing the server to not reload on file changes. + + +# Dependency Management + +> es6 modules + +> commonjs + +> amd + + +## require with expression + +A context is created if your request contains expressions, so the __exact__ module is not known on compile time. + +Example: + +```javascript +require('./template/' + name + '.ejs'); +``` + +webpack parses the `require()` call and extracts some information: + +```code +Directory: ./template +Regular expression: /^.*\.ejs$/ +``` + +__context module__ + +A context module is generated. It contains references to __all modules in that directory__ that can be required with a request matching the regular expression. The context module contains a map which translates requests to module ids. + +Example: + +```json +{ + "./table.ejs": 42, + "./table-row.ejs": 43, + "./directory/folder.ejs": 44 +} +``` + +The context module also contains some runtime logic to access the map. + +This means dynamic requires are supported but will cause all possible modules to be included in the bundle. + + +## `require.context` + +You can create your own context with the `require.context()` function. + +It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched +too, and a regular expression to match files against. + +webpack parses for `require.context()` in the code while building. + +The syntax is as follows: + +```javascript +require.context(directory, useSubdirectories = false, regExp = /^\.\//); +``` + +Examples: + +```javascript +require.context('./test', false, /\.test\.js$/); +// a context with files from the test directory that can be required with a request endings with `.test.js`. +``` + +```javascript +require.context('../', true, /\.stories\.js$/); +// a context with all files in the parent folder and descending folders ending with `.stories.js`. +``` + +W> The arguments passed to `require.context` must be literals! + + +### context module API + +A context module exports a (require) function that takes one argument: the request. + +The exported function has 3 properties: `resolve`, `keys`, `id`. + +- `resolve` is a function and returns the module id of the parsed request. +- `keys` is a function that returns an array of all possible requests that the context module can handle. + +This can be useful if you want to require all files in a directory or matching a pattern, Example: + +```javascript +function importAll (r) { + r.keys().forEach(r); +} + +importAll(require.context('../components/', true, /\.js$/)); +``` + +```javascript +var cache = {}; + +function importAll (r) { + r.keys().forEach(key => cache[key] = r(key)); +} + +importAll(require.context('../components/', true, /\.js$/)); +// At build-time cache will be populated with all required modules. +``` + +- `id` is the module id of the context module. This may be useful for `module.hot.accept`. + + +# Public Path + +The `publicPath` configuration option can be quite useful in a variety of scenarios. It allows you to specify the base path for all the assets within your application. + + +## Use Cases + +There are a few use cases in real applications where this feature becomes especially neat. Essentially, every file emitted to your `output.path` directory will be referenced from the `output.publicPath` location. This includes child chunks (created via [code splitting](/guides/code-splitting/)) and any other assets (e.g. images, fonts, etc.) that are a part of your dependency graph. + +### Environment Based + +In development for example, we might have an `assets/` folder that lives on the same level of our index page. This is fine, but what if we wanted to host all these static assets on a CDN in production? + +To approach this problem you can easily use a good old environment variable. Let's say we have a variable `ASSET_PATH`: + +``` js +import webpack from 'webpack'; + +// Try the environment variable, otherwise use root +const ASSET_PATH = process.env.ASSET_PATH || '/'; + +export default { + output: { + publicPath: ASSET_PATH + }, + + plugins: [ + // This makes it possible for us to safely use env vars on our code + new webpack.DefinePlugin({ + 'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH) + }) + ] +}; +``` + +### On The Fly + +Another possible use case is to set the `publicPath` on the fly. webpack exposes a global variable called `__webpack_public_path__` that allows you to do that. So, in your application's entry point, you can simply do this: + +```js +__webpack_public_path__ = process.env.ASSET_PATH; +``` + +That's all you need. Since we're already using the `DefinePlugin` on our +configuration, `process.env.ASSET_PATH` will always be defined so we can safely +do that. + +W> Be aware that if you use ES6 module imports in your entry file the `__webpack_public_path__` assignment will be done after the imports. In such cases, you'll have to move the public path assignment to its own dedicated module and then import it on top of your entry.js: + +```js +// entry.js +import './public-path'; +import './app'; +``` + + +# Integrations + +Let's start by clearing up a common misconception. webpack is a module bundler like [Browserify](http://browserify.org/) or [Brunch](http://brunch.io/). It is _not a task runner_ like [Make](https://www.gnu.org/software/make/), [Grunt](https://gruntjs.com/), or [Gulp](https://gulpjs.com/). Task runners handle automation of common development tasks such as linting, building, or testing your project. Compared to bundlers, task runners have a higher level focus. You can still benefit from their higher level tooling while leaving the problem of bundling to webpack. + +Bundlers help you get your JavaScript and stylesheets ready for deployment, transforming them into a format that's suitable for the browser. For example, JavaScript can be [minified](/plugins/terser-webpack-plugin) or [split into chunks](/guides/code-splitting) and [lazy-loaded](/guides/lazy-loading) to improve performance. Bundling is one of the most important challenges in web development, and solving it well can remove a lot of pain from the process. + +The good news is that, while there is some overlap, task runners and bundlers can play well together if approached in the right way. This guide provides a high-level overview of how webpack can be integrated into some of the more popular task runners. + + +## NPM Scripts + +Often webpack users use npm [`scripts`](https://docs.npmjs.com/misc/scripts) as their task runner. This is a good starting point. Cross-platform support can become a problem, but there are several workarounds for that. Many, if not most users, get by with simple npm `scripts` and various levels of webpack configuration and tooling. + +So while webpack's core focus is bundling, there are a variety of extensions that can enable you to use it for jobs typical of a task runner. Integrating a separate tool adds complexity, so be sure to weigh the pros and cons before going forward. + + +## Grunt + +For those using Grunt, we recommend the [`grunt-webpack`](https://www.npmjs.com/package/grunt-webpack) package. With `grunt-webpack` you can run webpack or [webpack-dev-server](https://github.com/webpack/webpack-dev-server) as a task, get access to stats within [template tags](https://gruntjs.com/api/grunt.template), split development and production configurations and more. Start by installing `grunt-webpack` as well as `webpack` itself if you haven't already: + +``` bash +npm install --save-dev grunt-webpack webpack +``` + +Then register a configuration and load the task: + +__Gruntfile.js__ + +``` js +const webpackConfig = require('./webpack.config.js'); + +module.exports = function(grunt) { + grunt.initConfig({ + webpack: { + options: { + stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development' + }, + prod: webpackConfig, + dev: Object.assign({ watch: true }, webpackConfig) + } + }); + + grunt.loadNpmTasks('grunt-webpack'); +}; +``` + +For more information, please visit the [repository](https://github.com/webpack-contrib/grunt-webpack). + + +## Gulp + +Gulp is also a fairly straightforward integration with the help of the [`webpack-stream`](https://github.com/shama/webpack-stream) package (a.k.a. `gulp-webpack`). In this case, it is unnecessary to install `webpack` separately as it is a direct dependency of `webpack-stream`: + +``` bash +npm install --save-dev webpack-stream +``` + +Just `require('webpack-stream')` instead of `webpack` and optionally pass it an configuration: + +__gulpfile.js__ + +``` js +var gulp = require('gulp'); +var webpack = require('webpack-stream'); +gulp.task('default', function() { + return gulp.src('src/entry.js') + .pipe(webpack({ + // Any configuration options... + })) + .pipe(gulp.dest('dist/')); +}); +``` + +For more information, please visit the [repository](https://github.com/shama/webpack-stream). + + +## Mocha + +The [`mocha-webpack`](https://github.com/zinserjan/mocha-webpack) utility can be used for a clean integration with Mocha. The repository offers more details on the pros and cons but essentially `mocha-webpack` is a simple wrapper that provides almost the same CLI as Mocha itself and provides various webpack functionality like an improved watch mode and improved path resolution. Here is a small example of how you would install it and use it to run a test suite (found within `./test`): + +``` bash +npm install --save-dev webpack mocha mocha-webpack +mocha-webpack 'test/**/*.js' +``` + +For more information, please visit the [repository](https://github.com/zinserjan/mocha-webpack). + + +## Karma + +The [`karma-webpack`](https://github.com/webpack-contrib/karma-webpack) package allows you to use webpack to pre-process files in [Karma](http://karma-runner.github.io/1.0/index.html). It also makes use of [`webpack-dev-middleware`](https://github.com/webpack/webpack-dev-middleware) and allows passing configurations for both. A simple example may look something like this: + +``` bash +npm install --save-dev webpack karma karma-webpack +``` + +__karma.conf.js__ + +``` js +module.exports = function(config) { + config.set({ + files: [ + { pattern: 'test/*_test.js', watched: false }, + { pattern: 'test/**/*_test.js', watched: false } + ], + preprocessors: { + 'test/*_test.js': [ 'webpack' ], + 'test/**/*_test.js': [ 'webpack' ] + }, + webpack: { + // Any custom webpack configuration... + }, + webpackMiddleware: { + // Any custom webpack-dev-middleware configuration... + } + }); +}; +``` + +For more information, please visit the [repository](https://github.com/webpack-contrib/karma-webpack). diff --git a/src/content/loaders/_loaders_all.md b/src/content/loaders/_loaders_all.md new file mode 100644 index 000000000000..a16e6814c65b --- /dev/null +++ b/src/content/loaders/_loaders_all.md @@ -0,0 +1,75 @@ + + +# Loaders + +webpack enables use of [loaders](/concepts/loaders) to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js. + +Loaders are activated by using `loadername!` prefixes in `require()` statements, or are automatically applied via regex from your webpack configuration – see [configuration](/concepts/loaders#configuration). + + +## Files + +- [`raw-loader`](/loaders/raw-loader) Loads raw content of a file (utf-8) +- [`val-loader`](/loaders/val-loader) Executes code as module and consider exports as JS code +- [`url-loader`](/loaders/url-loader) Works like the file loader, but can return a [data URL](https://tools.ietf.org/html/rfc2397) if the file is smaller than a limit +- [`file-loader`](/loaders/file-loader) Emits the file into the output folder and returns the (relative) URL +- [`ref-loader`](https://www.npmjs.com/package/ref-loader) Create dependencies between any files manually + + +## JSON + +- [`json-loader`](/loaders/json-loader) Loads a [JSON](http://json.org/) file (included by default) +- [`json5-loader`](/loaders/json5-loader) Loads and transpiles a [JSON 5](https://json5.org/) file +- [`cson-loader`](https://github.com/awnist/cson-loader) Loads and transpiles a [CSON](https://github.com/bevry/cson#what-is-cson) file + + +## Transpiling + +- [`script-loader`](/loaders/script-loader) Executes a JavaScript file once in global context (like in script tag), requires are not parsed +- [`babel-loader`](/loaders/babel-loader) Loads ES2015+ code and transpiles to ES5 using [Babel](https://babeljs.io/) +- [`buble-loader`](https://github.com/sairion/buble-loader) Loads ES2015+ code and transpiles to ES5 using [Bublé](https://buble.surge.sh/guide/) +- [`traceur-loader`](https://github.com/jupl/traceur-loader) Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler#readme) +- [`ts-loader`](https://github.com/TypeStrong/ts-loader) or [`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader) Loads [TypeScript](https://www.typescriptlang.org/) 2.0+ like JavaScript +- [`coffee-loader`](/loaders/coffee-loader) Loads [CoffeeScript](http://coffeescript.org/) like JavaScript +- [`fengari-loader`](https://github.com/fengari-lua/fengari-loader/) Loads Lua code using [fengari](https://fengari.io/) + + +## Templating + +- [`html-loader`](/loaders/html-loader) Exports HTML as string, require references to static resources +- [`pug-loader`](https://github.com/pugjs/pug-loader) Loads Pug and Jade templates and returns a function +- [`markdown-loader`](https://github.com/peerigon/markdown-loader) Compiles Markdown to HTML +- [`react-markdown-loader`](https://github.com/javiercf/react-markdown-loader) Compiles Markdown to a React Component using the markdown-parse parser +- [`posthtml-loader`](https://github.com/posthtml/posthtml-loader) Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) +- [`handlebars-loader`](https://github.com/pcardune/handlebars-loader) Compiles Handlebars to HTML +- [`markup-inline-loader`](https://github.com/asnowwolf/markup-inline-loader) Inline SVG/MathML files to HTML. It’s useful when applying icon font or applying CSS animation to SVG. +- [`twig-loader`](https://github.com/zimmo-be/twig-loader) Compiles Twig templates and returns a function + +## Styling + +- [`style-loader`](/loaders/style-loader) Add exports of a module as style to DOM +- [`css-loader`](/loaders/css-loader) Loads CSS file with resolved imports and returns CSS code +- [`less-loader`](/loaders/less-loader) Loads and compiles a LESS file +- [`sass-loader`](/loaders/sass-loader) Loads and compiles a SASS/SCSS file +- [`postcss-loader`](/loaders/postcss-loader) Loads and transforms a CSS/SSS file using [PostCSS](http://postcss.org) +- [`stylus-loader`](https://github.com/shama/stylus-loader) Loads and compiles a Stylus file + + +## Linting && Testing + +- [`mocha-loader`](/loaders/mocha-loader) Tests with [mocha](https://mochajs.org/) (Browser/NodeJS) +- [`eslint-loader`](https://github.com/webpack-contrib/eslint-loader) PreLoader for linting code using [ESLint](https://eslint.org/) +- [`jshint-loader`](/loaders/jshint-loader) PreLoader for linting code using [JSHint](http://jshint.com/about/) +- [`jscs-loader`](https://github.com/unindented/jscs-loader) PreLoader for code style checking using [JSCS](http://jscs.info/) +- [`coverjs-loader`](/loaders/coverjs-loader) PreLoader to determine the testing coverage using [CoverJS](https://github.com/arian/CoverJS) + + +## Frameworks + +- [`vue-loader`](https://github.com/vuejs/vue-loader) Loads and compiles [Vue Components](https://vuejs.org/v2/guide/components.html) +- [`polymer-loader`](https://github.com/webpack-contrib/polymer-webpack-loader) Process HTML & CSS with preprocessor of choice and `require()` Web Components like first-class modules +- [`angular2-template-loader`](https://github.com/TheLarkInn/angular2-template-loader) Loads and compiles [Angular](https://angular.io/) Components + + + +For more third-party loaders, see the list from [awesome-webpack](https://github.com/webpack-contrib/awesome-webpack#loaders). diff --git a/src/content/migrate/_migrate_all.md b/src/content/migrate/_migrate_all.md new file mode 100644 index 000000000000..c0c02cb9ff2b --- /dev/null +++ b/src/content/migrate/_migrate_all.md @@ -0,0 +1,786 @@ + + +# Migrate + +This section contains information about migrating from older versions of webpack to newer ones. + +# To v4 from v3 + +This guide only shows major changes that affect end users. For more details please see [the changelog](https://github.com/webpack/webpack/releases). + + +## Node.js v4 + +If you are still using Node.js v4 or lower, you need to upgrade your Node.js installation to Node.js v6 or higher. + + +## CLI + +The CLI has moved to a separate package: webpack-cli. You need to install it before using webpack, see [basic setup](/guides/getting-started/#basic-setup). + + +## Update plugins + +Many 3rd-party plugins need to be upgraded to their latest version to be compatible. + + +## mode + +Add the new [`mode`](/concepts/mode/) option to your config. Set it to production or development in your configuration depending on config type. + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + mode: 'production', +} +``` + +Alternatively you can pass it via CLI: `--mode production`/`--mode development` + +## Deprecated/Removed plugins + +These plugins can be removed from configuration as they are default in production mode: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NoEmitOnErrorsPlugin(), +- new ModuleConcatenationPlugin(), +- new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }) +- new UglifyJsPlugin() + ], +} +``` + +These plugins are default in development mode + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NamedModulesPlugin() + ], +} +``` + +These plugins were deprecated and are now removed: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NoErrorsPlugin(), +- new NewWatchingPlugin() + ], +} +``` + + +## CommonsChunkPlugin + +The `CommonsChunkPlugin` was removed. Instead the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) options can be used. + +See documentation of the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) for more details. The default configuration may already suit your needs. + +T> When generating the HTML from the stats you can use `optimization.splitChunks.chunks: "all"` which is the optimal configuration in most cases. + +## import() and CommonJS + +When using `import()` to load non-ESM the result has changed in webpack 4. Now you need to access the `default` property to get the value of `module.exports`. + +__non-esm.js__ + +``` javascript +module.exports = { + sayHello: () => { + console.log('hello world'); + } +}; +``` + +__example.js__ + +``` javascript +function sayHello() { + import('./non-esm.js').then(module => { + module.default.sayHello(); + }); +} +``` + +## json and loaders + +When using a custom loader to transform `.json` files you now need to change the module `type`: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + rules: [ + { + test: /config\.json$/, + loader: 'special-loader', ++ type: 'javascript/auto', + options: {...} + } + ] +}; +``` + +When still using the `json-loader`, it can be removed: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + rules: [ + { +- test: /\.json$/, +- loader: 'json-loader' + } + ] +}; +``` + +## module.loaders + +`module.loaders` were deprecated since webpack 2 and are now removed in favor of [`module.rules`](/configuration/module/#rule). + + +# To v2 or v3 from v1 + +The following sections describe the major changes from webpack 1 to 2. + +T> Note that there were far fewer changes between 2 and 3, so that migration shouldn't be too bad. If you are running into issues, please see [the changelog](https://github.com/webpack/webpack/releases) for details. + + +## `resolve.root`, `resolve.fallback`, `resolve.modulesDirectories` + +These options were replaced by a single option `resolve.modules`. See [resolving](/configuration/resolve) for more usage. + +``` diff + resolve: { +- root: path.join(__dirname, "src") ++ modules: [ ++ path.join(__dirname, "src"), ++ "node_modules" ++ ] + } +``` + + +## `resolve.extensions` + +This option no longer requires passing an empty string. This behavior was moved to `resolve.enforceExtension`. See [resolving](/configuration/resolve) for more usage. + + +## `resolve.*` + +Several APIs were changed here. Not listed in detail as it's not commonly used. See [resolving](/configuration/resolve) for details. + + +## `module.loaders` is now `module.rules` + +The old loader configuration was superseded by a more powerful rules system, which allows configuration of loaders and more. +For compatibility reasons, the old `module.loaders` syntax is still valid and the old names are parsed. +The new naming conventions are easier to understand and are a good reason to upgrade the configuration to using `module.rules`. + +``` diff + module: { +- loaders: [ ++ rules: [ + { + test: /\.css$/, +- loaders: [ +- "style-loader", +- "css-loader?modules=true" ++ use: [ ++ { ++ loader: "style-loader" ++ }, ++ { ++ loader: "css-loader", ++ options: { ++ modules: true ++ } ++ } + ] + }, + { + test: /\.jsx$/, + loader: "babel-loader", // Do not use "use" here + options: { + // ... + } + } + ] + } +``` + + +## Chaining loaders + +Like in webpack 1, loaders can be chained to pass results from loader to loader. Using the [rule.use](/configuration/module#rule-use) + configuration option, `use` can be set to an array of loaders. +In webpack 1, loaders were commonly chained with `!`. This style is only supported using the legacy option `module.loaders`. + +``` diff + module: { +- loaders: [{ ++ rules: [{ + test: /\.less$/, +- loader: "style-loader!css-loader!less-loader" ++ use: [ ++ "style-loader", ++ "css-loader", ++ "less-loader" ++ ] + }] + } +``` + + +## Automatic `-loader` module name extension removed + +It is not possible anymore to omit the `-loader` extension when referencing loaders: + +``` diff + module: { + rules: [ + { + use: [ +- "style", ++ "style-loader", +- "css", ++ "css-loader", +- "less", ++ "less-loader", + ] + } + ] + } +``` + +You can still opt-in to the old behavior with the `resolveLoader.moduleExtensions` configuration option, but this is not recommended. + +``` diff ++ resolveLoader: { ++ moduleExtensions: ["-loader"] ++ } +``` + +See [#2986](https://github.com/webpack/webpack/issues/2986) for the reason behind this change. + + +## `json-loader` is not required anymore + +When no loader has been configured for a JSON file, webpack will automatically try to load the JSON +file with the [`json-loader`](https://github.com/webpack-contrib/json-loader). + +``` diff + module: { + rules: [ +- { +- test: /\.json/, +- loader: "json-loader" +- } + ] + } +``` + +[We decided to do this](https://github.com/webpack/webpack/issues/3363) in order to iron out environment differences + between webpack, node.js and browserify. + + +## Loaders in configuration resolve relative to context + +In __webpack 1__, configured loaders resolve relative to the matched file. However, in __webpack 2__, configured loaders resolve relative to the `context` option. + +This solves some problems with duplicate modules caused by loaders when using `npm link` or referencing modules outside of the `context`. + +You may remove some hacks to work around this: + +``` diff + module: { + rules: [ + { + // ... +- loader: require.resolve("my-loader") ++ loader: "my-loader" + } + ] + }, + resolveLoader: { +- root: path.resolve(__dirname, "node_modules") + } +``` + + +## `module.preLoaders` and `module.postLoaders` were removed: + +``` diff + module: { +- preLoaders: [ ++ rules: [ + { + test: /\.js$/, ++ enforce: "pre", + loader: "eslint-loader" + } + ] + } +``` + + +## `UglifyJsPlugin` sourceMap + +The `sourceMap` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. This means that if you are using source maps for minimized code or want correct line numbers for uglifyjs warnings, you need to set `sourceMap: true` for `UglifyJsPlugin`. + +``` diff + devtool: "source-map", + plugins: [ + new UglifyJsPlugin({ ++ sourceMap: true + }) + ] +``` + + +## `UglifyJsPlugin` warnings + +The `compress.warnings` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. +This means that if you want to see uglifyjs warnings, you need to set `compress.warnings` to `true`. + +``` diff + devtool: "source-map", + plugins: [ + new UglifyJsPlugin({ ++ compress: { ++ warnings: true ++ } + }) + ] +``` + + +## `UglifyJsPlugin` minimize loaders + +`UglifyJsPlugin` no longer switches loaders into minimize mode. The `minimize: true` setting needs to be passed via loader options in the long-term. See loader documentation for relevant options. + +The minimize mode for loaders will be removed in webpack 3 or later. + +To keep compatibility with old loaders, loaders can be switched to minimize mode via plugin: + +``` diff + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ minimize: true ++ }) + ] +``` + + +## `DedupePlugin` has been removed + +`webpack.optimize.DedupePlugin` isn't needed anymore. Remove it from your configuration. + + +## `BannerPlugin` - breaking change + +`BannerPlugin` no longer accepts two parameters, but a single options object. + +``` diff + plugins: [ +- new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true}); ++ new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true}); + ] +``` + + +## `OccurrenceOrderPlugin` is now on by default + +The `OccurrenceOrderPlugin` is now enabled by default and has been renamed (`OccurenceOrderPlugin` in webpack 1). +Thus make sure to remove the plugin from your configuration: + +``` diff + plugins: [ + // webpack 1 +- new webpack.optimize.OccurenceOrderPlugin() + // webpack 2 +- new webpack.optimize.OccurrenceOrderPlugin() + ] +``` + + +## `ExtractTextWebpackPlugin` - breaking change + +[ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) requires version 2 to work with webpack 2. + +`npm install --save-dev extract-text-webpack-plugin` + +The configuration changes for this plugin are mainly syntactical. + +### `ExtractTextPlugin.extract` + +```diff +module: { + rules: [ + { + test: /.css$/, +- loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" }) ++ use: ExtractTextPlugin.extract({ ++ fallback: "style-loader", ++ use: "css-loader", ++ publicPath: "/dist" ++ }) + } + ] +} +``` + + +### `new ExtractTextPlugin({options})` + +```diff +plugins: [ +- new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false }) ++ new ExtractTextPlugin({ ++ filename: "bundle.css", ++ disable: false, ++ allChunks: true ++ }) +] +``` + + +## Full dynamic requires now fail by default + +A dependency with only an expression (i. e. `require(expr)`) will now create an empty context instead of the context of the complete directory. + +Code like this should be refactored as it won't work with ES2015 modules. If this is not possible you can use the `ContextReplacementPlugin` to hint the compiler towards the correct resolving. + +?> Link to an article about dynamic dependencies. + +### Using custom arguments in CLI and configuration + +If you abused the CLI to pass custom arguments to the configuration like so: + +`webpack --custom-stuff` + +```js +// webpack.config.js +var customStuff = process.argv.indexOf('--custom-stuff') >= 0; +/* ... */ +module.exports = config; +``` + +You may notice that this is no longer allowed. The CLI is more strict now. + +Instead there is an interface for passing arguments to the configuration. This should be used instead. Future tools may rely on this. + +`webpack --env.customStuff` + +```js +module.exports = function(env) { + var customStuff = env.customStuff; + /* ... */ + return config; +}; +``` + +See [CLI](/api/cli). + + +## `require.ensure` and AMD `require` are asynchronous + +These functions are now always asynchronous instead of calling their callback synchronously if the chunk is already loaded. + +__`require.ensure` now depends upon native `Promise`s. If using `require.ensure` in an environment that lacks them then you will need a polyfill.__ + + +## Loader configuration is through `options` + +You can _no longer_ configure a loader with a custom property in the `webpack.config.js`. It must be done through the `options`. The following configuration with the `ts` property is no longer valid with webpack 2: + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader' + }] + }, + // does not work with webpack 2 + ts: { transpileOnly: false } +}; +``` + + +### What are `options`? + +Good question. Well, strictly speaking it's 2 possible things; both ways to configure a webpack loader. Classically `options` was called `query` and was a string which could be appended to the name of the loader. Much like a query string but actually with [greater powers](https://github.com/webpack/loader-utils#parsequery): + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader?' + JSON.stringify({ transpileOnly: false }) + }] + } +}; +``` + +But it can also be a separately specified object that's supplied alongside a loader: + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader', + options: { transpileOnly: false } + }] + } +}; +``` + + +## `LoaderOptionsPlugin` context + +Some loaders need context information and read them from the configuration. This needs to be passed via loader options in the long-term. See loader documentation for relevant options. + +To keep compatibility with old loaders, this information can be passed via plugin: + +``` diff + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ options: { ++ context: __dirname ++ } ++ }) + ] +``` + + +## `debug` + +The `debug` option switched loaders to debug mode in webpack 1. This needs to be passed via loader options in long-term. See loader documentation for relevant options. + +The debug mode for loaders will be removed in webpack 3 or later. + +To keep compatibility with old loaders, loaders can be switched to debug mode via a plugin: + +``` diff +- debug: true, + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ debug: true ++ }) + ] +``` + + +## Code Splitting with ES2015 + +In webpack 1, you could use [`require.ensure()`](/api/module-methods#require-ensure) as a method to lazily-load chunks for your application: + +```javascript +require.ensure([], function(require) { + var foo = require('./module'); +}); +``` + +The ES2015 Loader spec defines [`import()`](/api/module-methods#import-) as method to load ES2015 Modules dynamically on runtime. webpack treats `import()` as a split-point and puts the requested module in a separate chunk. `import()` takes the module name as argument and returns a Promise. + +```js +function onClick() { + import('./module').then(module => { + return module.default; + }).catch(err => { + console.log('Chunk loading failed'); + }); +} +``` + +Good news: Failure to load a chunk can now be handled because they are `Promise` based. + + +## Dynamic expressions + +It's possible to pass a partial expression to `import()`. This is handled similar to expressions in CommonJS (webpack creates a [context](/plugins/context-replacement-plugin/) with all possible files). + +`import()` creates a separate chunk for each possible module. + +```js +function route(path, query) { + return import(`./routes/${path}/route`) + .then(route => new route.Route(query)); +} +// This creates a separate chunk for each possible route +``` + + +## Mixing ES2015 with AMD and CommonJS + +As for AMD and CommonJS you can freely mix all three module types (even within the same file). webpack behaves similar to babel and node-eps in this case: + +```javascript +// CommonJS consuming ES2015 Module +var book = require('./book'); + +book.currentPage; +book.readPage(); +book.default === 'This is a book'; +``` + +```javascript +// ES2015 Module consuming CommonJS +import fs from 'fs'; // module.exports map to default +import { readFileSync } from 'fs'; // named exports are read from returned object+ + +typeof fs.readFileSync === 'function'; +typeof readFileSync === 'function'; +``` + +It is important to note that you will want to tell Babel to not parse these module symbols so webpack can use them. You can do this by setting the following in your `.babelrc` or `babel-loader` options. + +__.babelrc__ + +```json +{ + "presets": [ + ["es2015", { "modules": false }] + ] +} +``` + + +## Hints + +No need to change something, but opportunities + +### Template strings + +webpack now supports template strings in expressions. This means you can start using them in webpack constructs: + +``` diff +- require("./templates/" + name); ++ require(`./templates/${name}`); +``` + + +### Configuration Promise + +webpack now supports returning a `Promise` from the configuration file. This allows async processing in your configuration file. + +__webpack.config.js__ + +```js +module.exports = function() { + return fetchLangs().then(lang => ({ + entry: '...', + // ... + plugins: [ + new DefinePlugin({ LANGUAGE: lang }) + ] + })); +}; +``` + + +### Advanced loader matching + +webpack now supports more things to match on for loaders. + +```js +module.exports = { + //... + module: { + rules: [ + { + resource: /filename/, // matches "/path/filename.js" + resourceQuery: /^\?querystring$/, // matches "?querystring" + issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js" + } + ] + } +}; +``` + + +### More CLI options + +There are some new CLI options for you to use: + +`--define process.env.NODE_ENV="production"` See [`DefinePlugin`](/plugins/define-plugin/). + +`--display-depth` displays the distance to the entry point for each module. + +`--display-used-exports` display info about which exports are used in a module. + +`--display-max-modules` sets the number for modules displayed in the output (defaults to 15). + +`-p` also defines `process.env.NODE_ENV` to `"production"` now. + + +## Loader changes + +Changes only relevant for loader authors. + + +### Cacheable + +Loaders are now cacheable by default. Loaders must opt-out if they are not cacheable. + +``` diff + // Cacheable loader + module.exports = function(source) { +- this.cacheable(); + return source; + } +``` + +``` diff + // Not cacheable loader + module.exports = function(source) { ++ this.cacheable(false); + return source; + } +``` + + +### Complex options + +__webpack 1__ only supports `JSON.stringify`-able options for loaders. + +__webpack 2__ now supports any JS object as loader options. + +Before webpack [2.2.1](https://github.com/webpack/webpack/releases/tag/v2.2.1) (i.e. from 2.0.0 through 2.2.0), using complex options required using `ident` for the `options` object to allow its reference from other loaders. __This was removed in 2.2.1__ and thus current migrations do not require any use of the `ident` key. + +```diff +{ + test: /\.ext/ + use: { + loader: '...', + options: { +- ident: 'id', + fn: () => require('./foo.js') + } + } +} +``` diff --git a/src/content/plugins/_plugins_all.md b/src/content/plugins/_plugins_all.md new file mode 100644 index 000000000000..65d63475ab80 --- /dev/null +++ b/src/content/plugins/_plugins_all.md @@ -0,0 +1,11 @@ + + +# MinChunkSizePlugin + +Keep chunk size above the specified limit by merging chunks that are smaller than the `minChunkSize`. + +``` js +new webpack.optimize.MinChunkSizePlugin({ + minChunkSize: 10000 // Minimum number of characters +}); +``` From 2cf4fcaa63db30b244ea1325a7f0746ef84656e4 Mon Sep 17 00:00:00 2001 From: Axel D <SetTrend@users.noreply.github.com> Date: Sun, 13 Jan 2019 22:55:36 +0100 Subject: [PATCH 02/13] _all.md files removed, .gitigore amened to exclude _all.md files from being checked in. --- .gitignore | 1 + src/content/_all.md | 262 - src/content/api/_api_all.md | 3189 ---------- src/content/concepts/_concepts_all.md | 1086 ---- .../configuration/_configuration_all.md | 5315 ----------------- src/content/contribute/_contribute_all.md | 979 --- src/content/guides/_guides_all.md | 4880 --------------- src/content/loaders/_loaders_all.md | 75 - src/content/migrate/_migrate_all.md | 786 --- src/content/plugins/_plugins_all.md | 11 - 10 files changed, 1 insertion(+), 16583 deletions(-) delete mode 100644 src/content/_all.md delete mode 100644 src/content/api/_api_all.md delete mode 100644 src/content/concepts/_concepts_all.md delete mode 100644 src/content/configuration/_configuration_all.md delete mode 100644 src/content/contribute/_contribute_all.md delete mode 100644 src/content/guides/_guides_all.md delete mode 100644 src/content/loaders/_loaders_all.md delete mode 100644 src/content/migrate/_migrate_all.md delete mode 100644 src/content/plugins/_plugins_all.md diff --git a/.gitignore b/.gitignore index cbdc7c1002d9..7a30f590d9a6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ starter-kits-data.json .DS_Store yarn-error.log package-lock.json +src/content/**/*_all.md \ No newline at end of file diff --git a/src/content/_all.md b/src/content/_all.md deleted file mode 100644 index fb91d2979380..000000000000 --- a/src/content/_all.md +++ /dev/null @@ -1,262 +0,0 @@ - - -# Comparison - -webpack is not the only module bundler out there. If you are choosing between using webpack or any of the bundlers below, here is a feature-by-feature comparison on how webpack fares against the current competition. - -| Feature | webpack/webpack | jrburke/requirejs | substack/node-browserify | jspm/jspm-cli | rollup/rollup | brunch/brunch | -|---------|-----------------|-------------------|--------------------------|---------------|---------------|---------------| -| Additional chunks are loaded on demand | __yes__ | __yes__ | no | [System.import](https://github.com/systemjs/systemjs/blob/master/docs/system-api.md#systemimportmodulename--normalizedparentname---promisemodule) | no | no | -| AMD `define` | __yes__ | __yes__ | [deamdify](https://github.com/jaredhanson/deamdify) | yes | [rollup-plugin-amd](https://github.com/piuccio/rollup-plugin-amd) | yes | -| AMD `require` | __yes__ | __yes__ | no | yes | no | yes | -| AMD `require` loads on demand | __yes__ | with manual configuration | no | yes | no | no | -| CommonJS `exports` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | -| CommonJS `require` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | -| CommonJS `require.resolve` | __yes__ | no | no | no | no | | -| Concat in require `require("./fi" + "le")` | __yes__ | no♦ | no | no | no | | -| Debugging support | __SourceUrl, SourceMaps__ | not required | SourceMaps | __SourceUrl, SourceMaps__ | __SourceUrl, SourceMaps__ | SourceMaps | -| Dependencies | 19MB / 127 packages | 11MB / 118 packages | __1.2MB / 1 package__ | 26MB / 131 packages | ?MB / 3 packages | | -| ES2015 `import`/`export` | __yes__ (webpack 2) | no | no | __yes__ | __yes__ | yes, via [es6 module transpiler](https://github.com/gcollazo/es6-module-transpiler-brunch) -| Expressions in require (guided) `require("./templates/" + template)` | __yes (all files matching included)__ | no♦ | no | no | no | no | -| Expressions in require (free) `require(moduleName)` | with manual configuration | no♦ | no | no | no | | -| Generate a single bundle | __yes__ | yes♦ | yes | yes | yes | yes | -| Indirect require `var r = require; r("./file")` | __yes__ | no♦ | no | no | no | | -| Load each file separate | no | yes | no | yes | no | no | -| Mangle path names | __yes__ | no | partial | yes | not required (path names are not included in the bundle) | no | -| Minimizing | terser | uglify, closure compiler | [uglifyify](https://github.com/hughsk/uglifyify) | yes | [uglify-plugin](https://github.com/TrySound/rollup-plugin-uglify) | [UglifyJS-brunch](https://github.com/brunch/uglify-js-brunch) -| Multi pages build with common bundle | with manual configuration | __yes__ | with manual configuration | with bundle arithmetic | no | no| -| Multiple bundles | __yes__ | with manual configuration | with manual configuration | yes | no | yes | -| Node.js built-in libs `require("path")` | __yes__ | no | __yes__ | __yes__ | [node-resolve-plugin](https://github.com/rollup/rollup-plugin-node-resolve) | | -| Other Node.js stuff | process, __dir/filename, global | - | process, __dir/filename, global | process, __dir/filename, global for cjs | global ([commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs)) | | -| Plugins | __yes__ | yes | __yes__ | yes | yes | yes | -| Preprocessing | __loaders, [transforms](https://github.com/webpack-contrib/transform-loader)__ | loaders | transforms | plugin translate | plugin transforms | compilers, optimizers | -| Replacement for browser | `web_modules`, `.web.js`, package.json field, alias config option | alias option | package.json field, alias option | package.json, alias option | no | | -| Requirable files | file system | __web__ | file system | through plugins | file system or through plugins | file system | -| Runtime overhead | __243B + 20B per module + 4B per dependency__ | 14.7kB + 0B per module + (3B + X) per dependency | 415B + 25B per module + (6B + 2X) per dependency | 5.5kB for self-executing bundles, 38kB for full loader and polyfill, 0 plain modules, 293B CJS, 139B ES2015 System.register before gzip | __none for ES2015 modules__ (other formats may have) | | -| Watch mode | yes | not required | [watchify](https://github.com/browserify/watchify) | not needed in dev | [rollup-watch](https://github.com/rollup/rollup-watch) | yes | - -♦ in production mode (opposite in development mode) - -X is the length of the path string - - -## Bundling vs. Loading - -It's important to note some key differences between _loading_ and _bundling_ modules. A tool like [SystemJS](https://github.com/systemjs/systemjs), which can be found under the hood of [JSPM](https://github.com/jspm/jspm-cli), is used to load and transpile modules at runtime in the browser. This differs significantly from webpack, where modules are transpiled (through "loaders") and bundled before hitting the browser. - -Each method has its advantages and disadvantages. Loading and transpiling modules at runtime can add a lot of overhead for larger sites and applications comprised of many modules. For this reason, SystemJS makes more sense for smaller projects where fewer modules are required. However, this may change a bit as [HTTP/2](https://http2.github.io/) will improve the speed at which files can be transferred from server to client. Note that HTTP/2 doesn't change anything about _transpiling_ modules, which will always take longer when done client-side. - - -# Branding Guidelines - -Here you can find __webpack__ project brand guidelines, assets, and license. See our official [media repository](https://github.com/webpack/media) for more information and to find the [license](https://github.com/webpack/media/blob/master/LICENSE) that governs this work. Click any of the images to download them. - - -## The Name - -webpack should __always__ be written in lower-case letters, even at the beginning of a sentence. - - -## Logo - -The webpack logo should be placed on a white background with enough space around it like this: - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-white-bg.png" alt="webpack logo default with proper spacing on light background" /> - -[svg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.jpg) - -Just double the size of the inner dark blue cube to get an idea how much space the logo should have. - -For dark backgrounds, you can use the negative version of the logo: - -<div style="display: block; background: #111;"> - <img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-dark-bg.png" alt="webpack logo default with proper spacing on light background" /> -</div> - -[svg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.jpg) - -T> Please use the __icon + text__ whenever possible. - - -## Icon only - -__The icon is designed to be used in layout-constrained areas. As previously stated, please prefer icon + text.__ - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon.png" width="250" alt="icon example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon.jpg) - -Square-sized icon for bigger areas (like avatars or profile pictures): - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-big.png" width="250" alt="icon square big example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon-square-big.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-big.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-big.jpg) - -Square-sized icon for smaller areas (like favicons): - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-small.png" width="50" alt="icon square small example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon-square-small.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-small.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-small.jpg) - -T> For those of you following our guidelines and have gotten this far, we've made a special smaller size image used especially for custom emoji (like in a slack or gitter channel ;)) - -<img src="/assets/icon-square-small-slack.png" width="50" alt="icon square small example"> - - -## Font - -We use the beautiful [Geomanist Medium](http://atipofoundry.com/fonts/geomanist) font from the extremely talented folks at the [Atipo Foundry](http://atipofoundry.com/) who provide the entire font family at a 'pay what you want' model. - - -## Color Palette - -The following colors are used throughout the site in various combinations and on our fancy clothing line launched with the help of [Open Collective](https://opencollective.com/) and [Threadless](https://medium.com/u/840563ee2a56) over at the [official webpack store](https://webpack.threadless.com/collections/the-final-release-collection/)! - -| Color Name | HEX Code | RGB Code | Sample -|---------------|---------------|-----------------------|------------------------------- -| Malibu: | HEX `#8dd6f9` | `rgb: 141, 214, 249` | <div style="background-color: #8dd6f9;"> </div> -| Denim: | HEX `#1d78c1` | `rgb: 29, 120, 193` | <div style="background-color: #1d78c1;"> </div> -| Fiord: | HEX `#465E69` | `rgb: 70, 94, 105` | <div style="background-color: #465E69;"> </div> -| Outer Space: | HEX `#2B3A42` | `rgb: 43, 58, 66` | <div style="background-color: #2B3A42;"> </div> -| White: | HEX `#ffffff` | `rgb: 255, 255, 255` | <div style="background-color: #ffffff;"> </div> -| Concrete: | HEX `#f2f2f2` | `rgb: 242, 242, 242` | <div style="background-color: #f2f2f2;"> </div> -| Alto: | HEX `#dedede` | `rgb: 222, 222, 222` | <div style="background-color: #dedede;"> </div> -| Dusty Gray: | HEX `#999999` | `rgb: 153, 153, 153` | <div style="background-color: #999999;"> </div> -| Dove Gray: | HEX `#666666` | `rgb: 102, 102, 102` | <div style="background-color: #666666;"> </div> -| Emperor: | HEX `#535353` | `rgb: 83, 83, 83` | <div style="background-color: #535353;"> </div> -| Mine Shaft: | HEX `#333333` | `rgb: 51, 51, 51` | <div style="background-color: #333333;"> </div> - -In addition, you can grab the following file types directly from these links: - -[psd](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.psd) | [png](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.png) - | [ai](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.ai) | [svg](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.svg) - - -## License - -The logo and the brand name are __not MIT licensed__. Please check [our LICENSE](https://github.com/webpack/media/blob/master/LICENSE) for usage guidelines. - - -# Glossary - -This index lists common terms used throughout the webpack ecosystem. - - -## A - -- [__Asset__](/guides/asset-management/): This a general term for the images, fonts, media, and any other kind of files that are typically used in websites and other applications. These typically end up as individual files within the [output](/glossary#o) but can also be inlined via things like the [style-loader](/loaders/style-loader) or [url-loader](/loaders/url-loader). - - -## B - -- [__Bundle__](/guides/getting-started/#creating-a-bundle): Produced from a number of distinct modules, bundles contain the final versions of source files that have already undergone the loading and compilation process. -- [__Bundle Splitting__](/guides/code-splitting): This process offers one way of optimizing a build, allowing webpack to generate multiple bundles for a single application. As a result, each bundle can be isolated from changes effecting others, reducing the amount of code that needs to be republished and therefore re-downloaded by the client and taking advantage of browser caching. - - -## C - -- __Chunk__: This webpack-specific term is used internally to manage the bundling process. Bundles are composed out of chunks, of which there are several types (e.g. entry and child). Typically, _chunks_ directly correspond with the output _bundles_ however, there are some configurations that don't yield a one-to-one relationship. -- [__Code Splitting__](/guides/code-splitting/): Refers to dividing your code into various bundles/chunks which you can then load on demand instead of loading a single bundle containing everything. -- [__Configuration__](/concepts/configuration/): webpack config file is a plain old JavaScript file that exports an object. This object is then processed by webpack based upon its defined properties. - - -## D - -- [__Dependency Graph__](/concepts/dependency-graph): Any time one file depends on another, webpack treats this as a _dependency_. Starting from an entry point(s), webpack recursively builds a dependency graph that includes every module/asset your application needs. - - -## E - -- [__Entry Point__](/concepts/entry-points): The entry point tells webpack where to start and follows the graph of dependencies to know what to bundle. You can think of your application's entry point(s) as the __contextual root(s)__ of what you want bundled. - - -## F - -## G - -## H - -- [__Hot Module Replacement (HMR)__](/concepts/hot-module-replacement): A process that exchanges, adds, or removes `modules` while an application is running without a full page reload. - - -## I - -## J - -## K - -## L - -- [__Loaders__](/concepts/loaders): Transformations that are applied on the source code of a module. They allow you to pre-process files as you `require()` or "load" them. Similar to a 'task-runner'. - - -## M - -- [__Module__](/concepts/modules): Discrete chunks of functionality that provide a smaller surface area than a full program. Well-written modules provide solid abstractions and encapsulation boundaries which make up a coherent design and clear purpose. -- [__Module Resolution__](/concepts/module-resolution/): A module can be required as a dependency from another module and a resolver is a library which helps in locating a module by its absolute path.. Modules are searched for inside all directories specified in `resolve.modules`. - - -## N - -## O - -- [__Output__](/concepts/output): Option(s) specifying where to output the compiled files to disk. - > _Note, that while there can be multiple entry points, only one output configuration is specified._ - - -## P - -- [__Plugin__](/concepts/plugins): A JavaScript object that has an `apply` property. This `apply` property is called by the webpack compiler, giving access to the entire compilation lifecycle. These packages will typically extend compilation functionality in one way or another. - - -## Q - -## R - -- [__Request__](/guides/dependency-management/): Refers to the expression in the require/import statement, e.g. _require("./template/" + name + ".ejs")_, the request is _"./template/" + name + ".ejs"_. - -## S - -## T - -- [__Target__](/configuration/target/): User configured deployment target(s) [listed here](/configuration/target/) to compile for a specific environment like the browser, NodeJS, or Electron. -- [__Tree Shaking__](/guides/tree-shaking/): Unused/Excess code elimination, or more precisely, live code importing. Compilers like webpack will accomplish this by analyzing the various kinds `import` statements and usage of the imported code to determine what parts of dependencies are actually being utilized, dropping parts of the "tree" that are not. - - -## U - -## V - -- [__Vendor Entry Point__](/concepts/entry-points/#separate-app-and-vendor-entries): Create dependency graphs starting at both `app.js` and `vendors.js`. These graphs are completely separate and independent of each other to allow leverage of `CommonsChunkPlugin` and extract any vendor references from your app bundle into your vendor bundle. Helps achieve a common pattern in webpack known as [long-term vendor-caching](/guides/caching/). - - -## W - -- [__webpack__](/): A highly configurable [module](/concepts/modules) bundler for modern JavaScript applications - - -## X - -## Y - -## Z - - -# License - -## webpack - -webpack is [MIT licensed](https://github.com/webpack/webpack/blob/master/LICENSE). - -## webpack logo and icon - -The webpack logo and icon are under a different license which can be -found [here](https://github.com/webpack/media). - -## webpack documentation - -The content on [https://webpack.js.org/](https://webpack.js.org/) is available under [Creative Commons BY 4.0](https://creativecommons.org/licenses/by/4.0/) license meaning attribution is required should you use the content elsewhere. - -## webpack code samples - -The code samples use [CC0 1.0 Universal (CC0 1.0) (Public Domain)](https://creativecommons.org/publicdomain/zero/1.0/) and you are free to use them as you like. diff --git a/src/content/api/_api_all.md b/src/content/api/_api_all.md deleted file mode 100644 index d54e6da2b86f..000000000000 --- a/src/content/api/_api_all.md +++ /dev/null @@ -1,3189 +0,0 @@ - - -# Compiler Hooks - -The `Compiler` module is the main engine that creates a compilation instance -with all the options passed through the [CLI](/api/cli) or [Node API](/api/node). It extends the -`Tapable` class in order to register and call plugins. Most user facing plugins -are first registered on the `Compiler`. - -T> This module is exposed as `webpack.Compiler` and can be used directly. See -[this example](https://github.com/pksjce/webpack-internal-examples/tree/master/compiler-example) -for more information. - -When developing a plugin for webpack, you might want to know where each hook is called. To learn this, search for `hooks.<hook name>.call` across the webpack source - - -## Watching - -The `Compiler` supports [watching](/api/node/#watching) which monitors the file -system and recompiles as files change. When in watch mode, the compiler will -emit the additional events such as `watchRun`, `watchClose`, and `invalid`. -This is typically used in [development](/guides/development), usually under -the hood of tools like `webpack-dev-server`, so that the developer doesn't -need to re-compile manually every time. Watch mode can also be entered via the -[CLI](/api/cli/#watch-options). - - -## Hooks - -The following lifecycle hooks are exposed by the `compiler` and can be accessed -as such: - -``` js -compiler.hooks.someHook.tap(/* ... */); -``` - -Depending on the hook type, `tapAsync` and `tapPromise` may also be available. - -For the description of hook types, see [the Tapable docs](https://github.com/webpack/tapable#hook-types). - - -### `entryOption` - -`SyncBailHook` - -Executes a plugin after [the `entry` configuration](https://webpack.js.org/configuration/entry-context/#entry) from webpack options has been processed. - - -### `afterPlugins` - -`SyncHook` - -Runs a plugin after setting up initial set of plugins. - -Parameters: `compiler` - - -### `afterResolvers` - -`SyncHook` - -Executes a plugin after resolver setup is complete. - -Parameters: `compiler` - - -### `environment` - -`SyncHook` - -Runs a plugin before the environment is prepared. - - -### `afterEnvironment` - -`SyncHook` - -Executes a plugin a environment setup is complete. - - -### `beforeRun` - -`AsyncSeriesHook` - -Adds a hook right before `compiler.run()` is executed. - -Parameters: `compiler` - - -### `run` - -`AsyncSeriesHook` - -Hook into the compiler before it begins reading records. - -Parameters: `compiler` - - -### `watchRun` - -`AsyncSeriesHook` - -Executes a plugin during watch mode after a new compilation is triggered -but before the compilation is actually started. - -Parameters: `compiler` - - -### `normalModuleFactory` - -`SyncHook` - -Runs a plugin after a `NormalModuleFactory` is created. - -Parameters: `normalModuleFactory` - - -### `contextModuleFactory` - -Runs a plugin after a `ContextModuleFactory` is created. - -Parameters: `contextModuleFactory` - - -### `beforeCompile` - -`AsyncSeriesHook` - -Executes a plugin after compilation parameters are created. - -Parameters: `compilationParams` - - -### `compile` - -`SyncHook` - -Hook into the compiler before a new compilation is created. - -Parameters: `compilationParams` - - -### `thisCompilation` - -`SyncHook` - -Executed before emitting the `compilation` event (see below). - -Parameters: `compilation` - - -### `compilation` - -`SyncHook` - -Runs a plugin after a compilation has been created. - -Parameters: `compilation` - - -### `make` - -`AsyncParallelHook` - -... - -Parameters: `compilation` - - -### `afterCompile` - -`AsyncSeriesHook` - -... - -Parameters: `compilation` - - -### `shouldEmit` - -`SyncBailHook` - -Can return true/false at this point - -Parameters: `compilation` - - -### `emit` - -`AsyncSeriesHook` - -Before emitting assets to output dir - -Parameters: `compilation` - - -### `afterEmit` - -`AsyncSeriesHook` - -After emitting assets to output dir - -Parameters: `compilation` - - -### `done` - -`AsyncSeriesHook` - -Compilation has completed. - -Parameters: `stats` - - -### `failed` - -`SyncHook` - -Compilation has failed. - -Parameters: `error` - - -### `invalid` - -`SyncHook` - -Watch compilation has been invalidated. - -Parameters: `fileName`, `changeTime` - - -### `watchClose` - -`SyncHook` - -Watch mode has stopped. - - -# Introduction - -A variety of interfaces are available to customize the compilation process. -Some features overlap between interfaces, e.g. a configuration option may be -available via a CLI flag, while others exist only through a single interface. -The following high-level information should get you started. - - -## CLI - -The Command Line Interface (CLI) to configure and interact with your build. It -is especially useful in the case of early prototyping and profiling. For the -most part, the CLI is simply used to kick off the process using a configuration -file and a few flags (e.g. `--env`). - -[Learn more about the CLI!](/api/cli) - - -## Module - -When processing modules with webpack, it is important to understand the -different module syntaxes -- specifically the [methods](/api/module-methods) -and [variables](/api/module-variables) -- that are supported. - -[Learn more about modules!](/api/module-methods) - - -## Node - -While most users can get away with just using the CLI along with a -configuration file, more fine-grained control of the compilation can be -achieved via the Node interface. This includes passing multiple configurations, -programmatically running or watching, and collecting stats. - -[Learn more about the Node API!](/api/node) - - -## Loaders - -Loaders are transformations that are applied to the source code of a module. -They are written as functions that accept source code as a parameter and return -a new version of that code with transformations applied. - -[Learn more about loaders!](/api/loaders) - - -## Plugins - -The plugin interface allows users to tap directly into the compilation process. -Plugins can register handlers on lifecycle hooks that run at different points -throughout a compilation. When each hook is executed, the plugin will have full -access to the current state of the compilation. - -[Learn more about plugins!](/api/plugins) - - -# Command Line Interface - -For proper usage and easy distribution of this configuration, webpack can be configured with `webpack.config.js`. Any parameters sent to the CLI will map to a corresponding parameter in the config file. - -Read the [installation guide](/guides/installation) if you don't already have webpack and CLI installed. - - -## Usage with config file - -```sh -webpack [--config webpack.config.js] -``` - -See [configuration](/configuration) for the options in the configuration file. - - -## Usage without config file - -```sh -webpack <entry> [<entry>] -o <output> -``` - -__`<entry>`__ - -A filename or a set of named filenames which act as the entry point to build your project. You can pass multiple entries (every entry is loaded on startup). If you pass a pair in the form `<name>=<request>` you can create an additional entry point. It will be mapped to the configuration option `entry`. - -__`<output>`__ - -A path and filename for the bundled file to be saved in. It will be mapped to the configuration options `output.path` and `output.filename`. - -__Example__ - -If your project structure is as follows - - -```bash -. -├── dist -├── index.html -└── src - ├── index.js - ├── index2.js - └── others.js -``` - -```bash -webpack src/index.js -o dist/bundle.js -``` - -This will bundle your source code with entry as `index.js` and the output bundle file will have a path of `dist` and the filename will be `bundle.js` - -```bash - | Asset | Size | Chunks | Chunk Names | - |-----------|---------|-------------|-------------| - | bundle.js | 1.54 kB | 0 [emitted] | index | - [0] ./src/index.js 51 bytes {0} [built] - [1] ./src/others.js 29 bytes {0} [built] -``` - -```bash -webpack index=./src/index.js entry2=./src/index2.js dist/bundle.js -``` - -This will form the bundle with both the files as separate entry points. - -```bash - | Asset | Size | Chunks | Chunk Names | - |-----------|---------|---------------|---------------| - | bundle.js | 1.55 kB | 0,1 [emitted] | index, entry2 | - [0] ./src/index.js 51 bytes {0} [built] - [0] ./src/index2.js 54 bytes {1} [built] - [1] ./src/others.js 29 bytes {0} {1} [built] -``` - - -### Common Options - -W> Note that Command Line Interface has a higher precedence for the arguments you use it with than your configuration file. For instance, if you pass [`--mode="production"`](/concepts/mode/#usage) to webpack CLI and your configuration file uses `development`, `production` will be used. - -__List all of the options available on the cli__ - -```bash -webpack --help -webpack -h -``` - -__Build source using a config file__ - -Specifies a different [configuration](/configuration) file to pick up. Use this if you want to specify something different than `webpack.config.js`, which is the default. - -```bash -webpack --config example.config.js -``` - -__Print result of webpack as a JSON__ - -```bash -webpack --json -webpack --json > stats.json -``` - -In every other case, webpack prints out a set of stats showing bundle, chunk and timing details. Using this option the output can be a JSON object. This response is accepted by webpack's [analyse tool](https://webpack.github.io/analyse/), or chrisbateman's [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/), or th0r's [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). The analyse tool will take in the JSON and provide all the details of the build in graphical form. - -### Environment Options - -When the webpack configuration [exports a function](/configuration/configuration-types#exporting-a-function), an "environment" may be passed to it. - -```bash -webpack --env.production # sets env.production == true -webpack --env.platform=web # sets env.platform == "web" -``` - -The `--env` argument accepts various syntaxes: - -Invocation | Resulting environment ----------------------------------------- | --------------------------- -`webpack --env prod` | `"prod"` -`webpack --env.prod` | `{ prod: true }` -`webpack --env.prod=1` | `{ prod: 1 }` -`webpack --env.prod=foo` | `{ prod: "foo" }` -`webpack --env.prod --env.min` | `{ prod: true, min: true }` -`webpack --env.prod --env min` | `[{ prod: true }, "min"]` -`webpack --env.prod=foo --env.prod=bar` | `{prod: [ "foo", "bar" ]}` - -T> See the [environment variables](/guides/environment-variables) guide for more information on its usage. - -### Config Options - -Parameter | Explanation | Input type | Default -------------------------- | ------------------------------------------- | ---------- | ------------------ -`--config` | Path to the config file | string | webpack.config.js or webpackfile.js -`--config-register, -r` | Preload one or more modules before loading the webpack configuration | array | -`--config-name` | Name of the config to use | string | -`--env` | Environment passed to the config, when it is a function | | -`--mode` | Mode to use, either "development" or "production" | string | - -### Output Options - -This set of options allows you to manipulate certain [output](/configuration/output) parameters of your build. - -Parameter | Explanation | Input type | Default -------------------------- | ------------------------------------------- | ---------- | ------------------ -`--output-chunk-filename` | The output filename for additional chunks | string | filename with [id] instead of [name] or [id] prefixed -`--output-filename` | The output filename of the bundle | string | [name].js -`--output-jsonp-function` | The name of the JSONP function used for chunk loading | string | webpackJsonp -`--output-library` | Expose the exports of the entry point as library | string | -`--output-library-target` | The type for exposing the exports of the entry point as library | string | var -`--output-path` | The output path for compilation assets | string | Current directory -`--output-pathinfo` | Include a comment with the request for every dependency | boolean | false -`--output-public-path` | The public path for the assets | string | / -`--output-source-map-filename` | The output filename for the SourceMap | string | [name].map or [outputFilename].map -`--build-delimiter` | Display custom text after build output | string | Default string is null. You could provide a string such as `=== Build done ===` - - -#### Example Usage - -```bash -webpack index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' - -| Asset | Size | Chunks | Chunk Names | -|--------------------------------------|---------|-------------|---------------| -| index2740fdca26e9348bedbec.bundle.js | 2.6 kB | 0 [emitted] | index2 | -| index740fdca26e9348bedbec.bundle.js | 2.59 kB | 1 [emitted] | index | - [0] ./src/others.js 29 bytes {0} {1} [built] - [1] ./src/index.js 51 bytes {1} [built] - [2] ./src/index2.js 54 bytes {0} [built] -``` - -```bash -webpack.js index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' --devtool source-map --output-source-map-filename='[name]123.map' - -| Asset | Size | Chunks | Chunk Names | -|--------------------------------------|---------|-------------|---------------| -| index2740fdca26e9348bedbec.bundle.js | 2.76 kB | 0 [emitted] | index2 | -| index740fdca26e9348bedbec.bundle.js | 2.74 kB | 1 [emitted] | index | -| index2123.map | 2.95 kB | 0 [emitted] | index2 | -| index123.map | 2.95 kB | 1 [emitted] | index | - [0] ./src/others.js 29 bytes {0} {1} [built] - [1] ./src/index.js 51 bytes {1} [built] - [2] ./src/index2.js 54 bytes {0} [built] -``` - - -### Debug Options - -This set of options allows you to better debug the application containing assets compiled with webpack - -Parameter | Explanation | Input type | Default value ------------- | ------------------------------------------------ | ---------- | ------------- -`--debug` | Switch loaders to debug mode | boolean | false -`--devtool` | Define [source map type](/configuration/devtool/) for the bundled resources | string | - -`--progress` | Print compilation progress in percentage | boolean | false -`--display-error-details` | Display details about errors | boolean | false - -### Module Options - -These options allow you to bind [modules](/configuration/module/) as allowed by webpack - -Parameter | Explanation | Usage --------------------- | -------------------------------------- | ---------------- -`--module-bind` | Bind a file extension to a loader | `--module-bind js=babel-loader` -`--module-bind-post` | Bind a file extension to a post loader | -`--module-bind-pre` | Bind a file extension to a pre loader | - - -### Watch Options - -These options makes the build [watch](/configuration/watch/) for changes in files of the dependency graph and perform the build again. - -Parameter | Explanation -------------------------- | ---------------------- -`--watch`, `-w` | Watch the filesystem for changes -`--watch-aggregate-timeout` | Timeout for gathering changes while watching -`--watch-poll` | The polling interval for watching (also enable polling) -`--watch-stdin`, `--stdin` | Exit the process when stdin is closed - - -### Optimize Options - -These options allow you to manipulate optimisations for a production build using webpack - -Parameter | Explanation | Plugin Used ---------------------------- | -------------------------------------------------------|---------------------- -`--optimize-max-chunks` | Try to keep the chunk count below a limit | [LimitChunkCountPlugin](/plugins/limit-chunk-count-plugin) -`--optimize-min-chunk-size` | Try to keep the chunk size above a limit | [MinChunkSizePlugin](/plugins/min-chunk-size-plugin) -`--optimize-minimize` | Minimize javascript and switches loaders to minimizing | [TerserPlugin](/plugins/terser-webpack-plugin/) & [LoaderOptionsPlugin](/plugins/loader-options-plugin/) - - -### Resolve Options - -These allow you to configure the webpack [resolver](/configuration/resolve/) with aliases and extensions. - -Parameter | Explanation | Example ----------------------- | ------------------------------------------------------- | ------------- -`--resolve-alias` | Setup a module alias for resolving | --resolve-alias jquery-plugin=jquery.plugin -`--resolve-extensions` | Setup extensions that should be used to resolve modules | --resolve-extensions .es6 .js .ts -`--resolve-loader-alias` | Minimize javascript and switches loaders to minimizing | - - -### Stats Options - -These options allow webpack to display various [stats](/configuration/stats/) and style them differently in the console output. - -Parameter | Explanation | Type --------------------------------- | ------------------------------------------------------------------ | ------- -`--color`, `--colors` | Force colors on the console [default: enabled for TTY output only] | boolean -`--no-color`, `--no-colors` | Force no colors on the console | boolean -`--display` | Select [display preset](/configuration/stats) (verbose, detailed, normal, minimal, errors-only, none; since webpack 3.0.0) | string -`--display-cached` | Display also cached modules in the output | boolean -`--display-cached-assets` | Display also cached assets in the output | boolean -`--display-chunks` | Display chunks in the output | boolean -`--display-depth` | Display distance from entry point for each module | boolean -`--display-entrypoints` | Display entry points in the output | boolean -`--display-error-details` | Display details about errors | boolean -`--display-exclude` | Exclude modules in the output | boolean -`--display-max-modules` | Sets the maximum number of visible modules in output | number -`--display-modules` | Display even excluded modules in the output | boolean -`--display-optimization-bailout` | Scope hoisting fallback trigger (since webpack 3.0.0) | boolean -`--display-origins` | Display origins of chunks in the output | boolean -`--display-provided-exports` | Display information about exports provided from modules | boolean -`--display-reasons` | Display reasons about module inclusion in the output | boolean -`--display-used-exports` | Display information about used exports in modules (Tree Shaking) | boolean -`--hide-modules` | Hides info about modules | boolean -`--sort-assets-by` | Sorts the assets list by property in asset | string -`--sort-chunks-by` | Sorts the chunks list by property in chunk | string -`--sort-modules-by` | Sorts the modules list by property in module | string -`--verbose` | Show more details | boolean - - -### Advanced Options - -Parameter | Explanation | Usage ------------------ | ---------------------------------------- | ----- -`--bail` | Abort the compilation on first error | -`--cache` | Enable in memory caching [Enabled by default for watch] | `--cache=false` -`--define` | Define any free variable, see [shimming](/guides/shimming) | `--define process.env.NODE_ENV="'development'"` -`--hot` | Enables [Hot Module Replacement](/concepts/hot-module-replacement) | `--hot=true` -`--labeled-modules` | Enables labeled modules [Uses LabeledModulesPlugin] | -`--plugin` | Load this [plugin](/configuration/plugins/) | -`--prefetch` | Prefetch the particular file | `--prefetch=./files.js` -`--provide` | Provide these modules as globals, see [shimming](/guides/shimming) | `--provide jQuery=jquery` -`--records-input-path` | Path to the records file (reading) | -`--records-output-path` | Path to the records file (writing) | -`--records-path` | Path to the records file | -`--target` | The [targeted](/configuration/target/) execution environment | `--target='node'` - -### Shortcuts - -Shortcut | Replaces ----------|---------------------------- --d | `--debug --devtool cheap-module-eval-source-map --output-pathinfo` --p | `--optimize-minimize --define process.env.NODE_ENV="production"`, see [building for production](/guides/production) - -### Profiling - -The `--profile` option captures timing information for each step of the compilation and includes this in the output. - -```bash -webpack --profile - -⋮ -[0] ./src/index.js 90 bytes {0} [built] - factory:22ms building:16ms = 38ms -``` - -For each module, the following details are included in the output as applicable: - -- `factory`: time to collect module metadata (e.g. resolving the filename) -- `building`: time to build the module (e.g. loaders and parsing) -- `dependencies`: time to identify and connect the module’s dependencies - -Paired with `--progress`, `--profile` gives you an in depth idea of which step in the compilation is taking how long. This can help you optimise your build in a more informed manner. - -```bash -webpack --progress --profile - -30ms building modules -1ms sealing -1ms optimizing -0ms basic module optimization -1ms module optimization -1ms advanced module optimization -0ms basic chunk optimization -0ms chunk optimization -1ms advanced chunk optimization -0ms module and chunk tree optimization -1ms module reviving -0ms module order optimization -1ms module id optimization -1ms chunk reviving -0ms chunk order optimization -1ms chunk id optimization -10ms hashing -0ms module assets processing -13ms chunk assets processing -1ms additional chunk assets processing -0ms recording -0ms additional asset processing -26ms chunk asset optimization -1ms asset optimization -6ms emitting -⋮ -``` - - -# Compilation Hooks - -The `Compilation` module is used by the `Compiler` to create new compilations -(or builds). A `compilation` instance has access to all modules and their -dependencies (most of which are circular references). It is the literal -compilation of all the modules in the dependency graph of an application. -During the compilation phase, modules are loaded, sealed, optimized, chunked, -hashed and restored. - -The `Compilation` class also extends `Tapable` and provides the following -lifecycle hooks. They can be tapped the same way as compiler hooks: - -``` js -compilation.hooks.someHook.tap(/* ... */); -``` - -As with the `compiler`, `tapAsync` and `tapPromise` may also be available -depending on the type of hook. - - -### `buildModule` - -`SyncHook` - -Triggered before a module build has started. - -Parameters: `module` - - -### `rebuildModule` - -`SyncHook` - -Fired before rebuilding a module. - -Parameters: `module` - - -### `failedModule` - -`SyncHook` - -Run when a module build has failed. - -Parameters: `module` `error` - - -### `succeedModule` - -`SyncHook` - -Executed when a module has been built successfully. - -Parameters: `module` - - -### `finishModules` - -`SyncHook` - -All modules have been built. - -Parameters: `modules` - - -### `finishRebuildingModule` - -`SyncHook` - -A module has been rebuilt. - -Parameters: `module` - - -### `seal` - -`SyncHook` - -Fired when the compilation stops accepting new modules. - - -### `unseal` - -`SyncHook` - -Fired when a compilation begins accepting new modules. - - -### `optimizeDependenciesBasic` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeDependencies` - -`SyncBailHook` - -Fired at the beginning of dependency optimization. - -Parameters: `modules` - - -### `optimizeDependenciesAdvanced` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `afterOptimizeDependencies` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimize` - -`SyncHook` - -Triggered at the beginning of the optimization phase. - - -### `optimizeModulesBasic` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeModules` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeModulesAdvanced` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `afterOptimizeModules` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimizeChunksBasic` - -`SyncBailHook` - -... - -Parameters: `chunks` - - -### `optimizeChunks` - -`SyncBailHook` - -Optimize the chunks. - -Parameters: `chunks` - - -### `optimizeChunksAdvanced` - -`SyncBailHook` - -... - -Parameters: `chunks` - - -### `afterOptimizeChunks` - -`SyncHook` - -Fired after chunk optimization has completed. - -Parameters: `chunks` - - -### `optimizeTree` - -`AsyncSeriesHook` - -Optimize the dependency tree asynchronously. - -Parameters: `chunks` `modules` - - -### `afterOptimizeTree` - -`SyncHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModulesBasic` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModules` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModulesAdvanced` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `afterOptimizeChunkModules` - -`SyncHook` - -... - -Parameters: `chunks` `modules` - - -### `shouldRecord` - -`SyncBailHook` - -... - - -### `reviveModules` - -`SyncHook` - -Restore module information from records. - -Parameters: `modules` `records` - - -### `optimizeModuleOrder` - -`SyncHook` - -Sort the modules in from most to least important. - -Parameters: `modules` - - -### `advancedOptimizeModuleOrder` - -`SyncHook` - -... - -Parameters: `modules` - - -### `beforeModuleIds` - -`SyncHook` - -... - -Parameters: `modules` - - -### `moduleIds` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimizeModuleIds` - -`SyncHook` - -... - -Parameters: `chunks` - - -### `afterOptimizeModuleIds` - -`SyncHook` - -... - -Parameters: `chunks` - - -### `reviveChunks` - -`SyncHook` - -Restore chunk information from records. - -Parameters: `modules` `records` - - -### `optimizeChunkOrder` - -`SyncHook` - -Sort the chunks in from most to least important. - -Parameters: `chunks` - - -### `beforeOptimizeChunkIds` - -`SyncHook` - -Fired before chunk `id` optimization. - -Parameters: `chunks` - - -### `optimizeChunkIds` - -`SyncHook` - -Optimize the `id` of each chunk. - -Parameters: `chunks` - - -### `afterOptimizeChunkIds` - -`SyncHook` - -Triggered after chunk `id` optimization has finished. - -Parameters: `chunks` - - -### `recordModules` - -`SyncHook` - -Store module info to the records. - -Parameters: `modules` `records` - - -### `recordChunks` - -`SyncHook` - -Store chunk info to the records. - -Parameters: `chunks` `records` - - -### `beforeHash` - -`SyncHook` - -Before the compilation is hashed. - - -### `afterHash` - -`SyncHook` - -After the compilation is hashed. - - -### `recordHash` - -`SyncHook` - -... - -Parameters: `records` - - -### `record` - -`SyncHook` - -Store information about the `compilation` to the `records`. - -Parameters: `compilation` `records` - - -### `beforeModuleAssets` - -`SyncHook` - -... - - -### `shouldGenerateChunkAssets` - -`SyncBailHook` - -... - - -### `beforeChunkAssets` - -`SyncHook` - -Before creating the chunk assets. - - -### `additionalChunkAssets` - -`SyncHook` - -Create additional assets for the chunks. - -Parameters: `chunks` - - -### `records` - -`SyncHook` - -... - -Parameters: `compilation` `records` - - -### `additionalAssets` - -`AsyncSeriesHook` - -Create additional assets for the compilation. This hook can be used to download -an image, for example: - -``` js -compilation.hooks.additionalAssets.tapAsync('MyPlugin', callback => { - download('https://img.shields.io/npm/v/webpack.svg', function(resp) { - if(resp.status === 200) { - compilation.assets['webpack-version.svg'] = toAsset(resp); - callback(); - } else { - callback(new Error('[webpack-example-plugin] Unable to download the image')); - } - }); -}); -``` - - -### `optimizeChunkAssets` - -`AsyncSeriesHook` - -Optimize any chunk assets. The assets are stored in `compilation.assets`. A -`Chunk` has a property `files` which points to all files created by a chunk. -Any additional chunk assets are stored in `compilation.additionalChunkAssets`. - -Parameters: `chunks` - -Here's an example that simply adds a banner to each chunk. - -``` js -compilation.hooks - .optimizeChunkAssets - .tapAsync('MyPlugin', (chunks, callback) => { - chunks.forEach(chunk => { - chunk.files.forEach(file => { - compilation.assets[file] = new ConcatSource( - '\/**Sweet Banner**\/', - '\n', - compilation.assets[file] - ); - }); - }); - - callback(); - }); -``` - - -### `afterOptimizeChunkAssets` - -`SyncHook` - -The chunk assets have been optimized. - -Parameters: `chunks` - -Here's an example plugin from [@boopathi](https://github.com/boopathi) that outputs exactly what went into each chunk. - -``` js -compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', chunks => { - chunks.forEach(chunk => { - console.log({ - id: chunk.id, - name: chunk.name, - includes: chunk.modules.map(module => module.request) - }); - }); -}); -``` - - -### `optimizeAssets` - -`AsyncSeriesHook` - -Optimize all assets stored in `compilation.assets`. - -Parameters: `assets` - - -### `afterOptimizeAssets` - -`SyncHook` - -The assets has been optimized. - -Parameters: `assets` - - -### `needAdditionalSeal` - -`SyncBailHook` - -... - - -### `afterSeal` - -`AsyncSeriesHook` - -... - - -### `chunkHash` - -`SyncHook` - -... - -Parameters: `chunk` `chunkHash` - - -### `moduleAsset` - -`SyncHook` - -An asset from a module was added to the compilation. - -Parameters: `module` `filename` - - -### `chunkAsset` - -`SyncHook` - -An asset from a chunk was added to the compilation. - -Parameters: `chunk` `filename` - - -### `assetPath` - -`SyncWaterfallHook` - -... - -Parameters: `filename` `data` - - -### `needAdditionalPass` - -`SyncBailHook` - -... - - -### `childCompiler` - -`SyncHook` - -... - -Parameters: `childCompiler` `compilerName` `compilerIndex` - - -### `normalModuleLoader` - -`SyncHook` - -The normal module loader is the function that actually loads all the modules -in the module graph (one-by-one). - -Parameters: `loaderContext` `module` - -### `dependencyReference` - -`SyncWaterfallHook` - -`Compilation.hooks.dependencyReference(depRef, dependency, module)` allows to change the references reported by dependencies. - -Parameters: `depRef` `dependency` `module` - - -# Module Methods - -This section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including [ES6](https://en.wikipedia.org/wiki/ECMAScript#6th_Edition_-_ECMAScript_2015), [CommonJS](https://en.wikipedia.org/wiki/CommonJS), and [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition). - -W> While webpack supports multiple module syntaxes, we recommend following a single syntax for consistency and to avoid odd behaviors/bugs. Here's [one example](https://github.com/webpack/webpack.js.org/issues/552) of mixing ES6 and CommonJS, however there are surely others. - - -## ES6 (Recommended) - -Version 2 of webpack supports ES6 module syntax natively, meaning you can use `import` and `export` without a tool like babel to handle this for you. Keep in mind that you will still probably need babel for other ES6+ features. The following methods are supported by webpack: - - -### `import` - -Statically `import` the `export`s of another module. - -``` javascript -import MyModule from './my-module.js'; -import { NamedExport } from './other-module.js'; -``` - -W> The keyword here is __statically__. Normal `import` statement cannot be used dynamically within other logic or contain variables. See the [spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) for more information and `import()` below for dynamic usage. - - -### `export` - -Export anything as a `default` or named export. - -``` javascript -// Named exports -export var Count = 5; -export function Multiply(a, b) { - return a * b; -} - -// Default export -export default { - // Some data... -}; -``` - - -### `import()` - -`import('path/to/module') -> Promise` - -Dynamically load modules. Calls to `import()` are treated as split points, meaning the requested module and it's children are split out into a separate chunk. - -T> The [ES2015 Loader spec](https://whatwg.github.io/loader/) defines `import()` as method to load ES2015 modules dynamically on runtime. - -``` javascript -if ( module.hot ) { - import('lodash').then(_ => { - // Do something with lodash (a.k.a '_')... - }); -} -``` - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -The spec for `import` doesn't allow control over the chunk's name or other properties as "chunks" are only a concept within webpack. Luckily webpack allows some special parameters via comments so as to not break the spec: - -``` js -// Single target -import( - /* webpackChunkName: "my-chunk-name" */ - /* webpackMode: "lazy" */ - 'module' -); - -// Multiple possible targets -import( - /* webpackInclude: /\.json$/ */ - /* webpackExclude: /\.noimport\.json$/ */ - /* webpackChunkName: "my-chunk-name" */ - /* webpackMode: "lazy" */ - `./locale/${language}` -); -``` - -```js -import(/* webpackIgnore: true */ 'ignored-module.js'); -``` - -`webpackIgnore`: Disables dynamic import parsing when set to `true`. - -W> Note that setting `webpackIgnore` to `true` opts out of code splitting. - -`webpackChunkName`: A name for the new chunk. Since webpack 2.6.0, the placeholders `[index]` and `[request]` are supported within the given string to an incremented number or the actual resolved filename respectively. - -`webpackMode`: Since webpack 2.6.0, different modes for resolving dynamic imports can be specified. The following options are supported: - -- `"lazy"` (default): Generates a lazy-loadable chunk for each `import()`ed module. -- `"lazy-once"`: Generates a single lazy-loadable chunk that can satisfy all calls to `import()`. The chunk will be fetched on the first call to `import()`, and subsequent calls to `import()` will use the same network response. Note that this only makes sense in the case of a partially dynamic statement, e.g. ``import(`./locales/${language}.json`)``, where there are multiple module paths that could potentially be requested. -- `"eager"`: Generates no extra chunk. All modules are included in the current chunk and no additional network requests are made. A `Promise` is still returned but is already resolved. In contrast to a static import, the module isn't executed until the call to `import()` is made. -- `"weak"`: Tries to load the module if the module function has already been loaded in some other way (i. e. another chunk imported it or a script containing the module was loaded). A `Promise` is still returned but, only successfully resolves if the chunks are already on the client. If the module is not available, the `Promise` is rejected. A network request will never be performed. This is useful for universal rendering when required chunks are always manually served in initial requests (embedded within the page), but not in cases where app navigation will trigger an import not initially served. - -T> Note that all options can be combined like so `/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */`. This is wrapped in a JavaScript object and executed using [node VM](https://nodejs.org/dist/latest-v8.x/docs/api/vm.html). You do not need to add curly brackets. - -`webpackInclude`: A regular expression that will be matched against during import resolution. Only modules that match __will be bundled__. - -`webpackExclude`: A regular expression that will be matched against during import resolution. Any module that matches __will not be bundled__. - -T> Note that `webpackInclude` and `webpackExclude` options do not interfere with the prefix. eg: `./locale`. - -W> Fully dynamic statements, such as `import(foo)`, __will fail__ because webpack requires at least some file location information. This is because `foo` could potentially be any path to any file in your system or project. The `import()` must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files. - -W> Every module that could potentially be requested on an `import()` call is included. For example, ``import(`./locale/${language}.json`)`` will cause every `.json` file in the `./locale` directory to be bundled into the new chunk. At run time, when the variable `language` has been computed, any file like `english.json` or `german.json` will be available for consumption. Using the `webpackInclude` and `webpackExclude` options allows us to add regex patterns that reduce the files that webpack will bundle for this import. - -W> The use of `System.import` in webpack [did not fit the proposed spec](https://github.com/webpack/webpack/issues/2163), so it was deprecated in webpack [2.1.0-beta.28](https://github.com/webpack/webpack/releases/tag/v2.1.0-beta.28) in favor of `import()`. - - -## CommonJS - -The goal of CommonJS is to specify an ecosystem for JavaScript outside the browser. The following CommonJS methods are supported by webpack: - - -### `require` - -``` javascript -require(dependency: String); -``` - -Synchronously retrieve the exports from another module. The compiler will ensure that the dependency is available in the output bundle. - -``` javascript -var $ = require('jquery'); -var myModule = require('my-module'); -``` - -W> Using it asynchronously may not have the expected effect. - - -### `require.resolve` - -``` javascript -require.resolve(dependency: String); -``` - -Synchronously retrieve a module's ID. The compiler will ensure that the dependency is available in the output bundle. See [`module.id`](/api/module-variables#module-id-commonjs-) for more information. - -W> Module ID is a number in webpack (in contrast to NodeJS where it is a string -- the filename). - - -### `require.cache` - -Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. - -W> This is only needed in rare cases for compatibility! - -``` javascript -var d1 = require('dependency'); -require('dependency') === d1; -delete require.cache[require.resolve('dependency')]; -require('dependency') !== d1; -``` - -``` javascript -// in file.js -require.cache[module.id] === module; -require('./file.js') === module.exports; -delete require.cache[module.id]; -require.cache[module.id] === undefined; -require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow -require.cache[module.id] !== module; -``` - - -### `require.ensure` - -W> `require.ensure()` is specific to webpack and superseded by `import()`. - -<!-- eslint-skip --> - -```js -require.ensure( - dependencies: String[], - callback: function(require), - errorCallback: function(error), - chunkName: String -) -``` - -Split out the given `dependencies` to a separate bundle that that will be loaded asynchronously. When using CommonJS module syntax, this is the only way to dynamically load dependencies. Meaning, this code can be run within execution, only loading the `dependencies` if certain conditions are met. - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `require.ensure` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -``` javascript -var a = require('normal-dep'); - -if ( module.hot ) { - require.ensure(['b'], function(require) { - var c = require('c'); - - // Do something special... - }); -} -``` - -The following parameters are supported in the order specified above: - -- `dependencies`: An array of strings declaring all modules required for the code in the `callback` to execute. -- `callback`: A function that webpack will execute once the dependencies are loaded. An implementation of the `require` function is sent as a parameter to this function. The function body can use this to further `require()` modules it needs for execution. -- `errorCallback`: A function that is executed when webpack fails to load the dependencies. -- `chunkName`: A name given to the chunk created by this particular `require.ensure()`. By passing the same `chunkName` to various `require.ensure()` calls, we can combine their code into a single chunk, resulting in only one bundle that the browser must load. - -W> Although the implementation of `require` is passed as an argument to the `callback` function, using an arbitrary name e.g. `require.ensure([], function(request) { request('someModule'); })` isn't handled by webpack's static parser. Use `require` instead, e.g. `require.ensure([], function(require) { require('someModule'); })`. - - - -## AMD - -Asynchronous Module Definition (AMD) is a JavaScript specification that defines an interface for writing and loading modules. The following AMD methods are supported by webpack: - - -### `define` (with factory) - -<!-- eslint-skip --> - -```js -define([name: String], [dependencies: String[]], factoryMethod: function(...)) -``` - -If `dependencies` are provided, `factoryMethod` will be called with the exports of each dependency (in the same order). If `dependencies` are not provided, `factoryMethod` is called with `require`, `exports` and `module` (for compatibility!). If this function returns a value, this value is exported by the module. The compiler ensures that each dependency is available. - -W> Note that webpack ignores the `name` argument. - -``` javascript -define(['jquery', 'my-module'], function($, myModule) { - // Do something with $ and myModule... - - // Export a function - return function doSomething() { - // ... - }; -}); -``` - -W> This CANNOT be used in an asynchronous function. - - -### `define` (with value) - -<!-- eslint-skip --> - -```js -define(value: !Function) -``` - -This will simply export the provided `value`. The `value` here can be anything except a function. - -``` javascript -define({ - answer: 42 -}); -``` - -W> This CANNOT be used in an async function. - - -### `require` (amd-version) - -<!-- eslint-skip --> - -```js -require(dependencies: String[], [callback: function(...)]) -``` - -Similar to `require.ensure`, this will split the given `dependencies` into a separate bundle that will be loaded asynchronously. The `callback` will be called with the exports of each dependency in the `dependencies` array. - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use AMD with older browsers (e.g. Internet Explorer 11), remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -``` javascript -require(['b'], function(b) { - var c = require('c'); -}); -``` - -W> There is no option to provide a chunk name. - - - -## Labeled Modules - -The internal `LabeledModulesPlugin` enables you to use the following methods for exporting and requiring within your modules: - - -### `export` label - -Export the given `value`. The label can occur before a function declaration or a variable declaration. The function name or variable name is the identifier under which the value is exported. - -<!-- eslint-skip --> - -```js -export: var answer = 42; -export: function method(value) { - // Do something... -}; -``` - -W> Using it in an async function may not have the expected effect. - - -### `require` label - -Make all exports from the dependency available in the current scope. The `require` label can occur before a string. The dependency must export values with the `export` label. CommonJS or AMD modules cannot be consumed. - -__some-dependency.js__ - -<!-- eslint-skip --> - -```js -export: var answer = 42; -export: function method(value) { - // Do something... -}; -``` - -<!-- eslint-skip --> - -```js -require: 'some-dependency'; -console.log(answer); -method(...); -``` - - - -## Webpack - -Aside from the module syntaxes described above, webpack also allows a few custom, webpack-specific methods: - - -### `require.context` - -<!-- eslint-skip --> - -```js -require.context( - directory: String, - includeSubdirs: Boolean /* optional, default true */, - filter: RegExp /* optional, default /^\.\/.*$/, any file */, - mode: String /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */ -) -``` - -Specify a whole group of dependencies using a path to the `directory`, an option to `includeSubdirs`, a `filter` for more fine grained control of the modules included, and a `mode` to define the way how loading will work. Underlying modules can then be easily resolved later on: - -```javascript -var context = require.context('components', true, /\.html$/); -var componentA = context.resolve('componentA'); -``` - -If `mode` is specified as "lazy", the underlying modules will be loaded asynchronously: - -```javascript -var context = require.context('locales', true, /\.json$/, 'lazy'); -context('localeA').then(locale => { - // do something with locale -}); -``` - -The full list of available modes and its behavior is described in [`import()`](#import-) documentation. - -### `require.include` - -<!-- eslint-skip --> - -```js -require.include(dependency: String) -``` - -Include a `dependency` without executing it. This can be used for optimizing the position of a module in the output chunks. - -``` javascript -require.include('a'); -require.ensure(['a', 'b'], function(require) { /* ... */ }); -require.ensure(['a', 'c'], function(require) { /* ... */ }); -``` - -This will result in following output: - -- entry chunk: `file.js` and `a` -- anonymous chunk: `b` -- anonymous chunk: `c` - -Without `require.include('a')` it would be duplicated in both anonymous chunks. - - -### `require.resolveWeak` - -Similar to `require.resolve`, but this won't pull the `module` into the bundle. It's what is considered a "weak" dependency. - -``` javascript -if(__webpack_modules__[require.resolveWeak('module')]) { - // Do something when module is available... -} -if(require.cache[require.resolveWeak('module')]) { - // Do something when module was loaded before... -} - -// You can perform dynamic resolves ("context") -// just as with other require/import methods. -const page = 'Foo'; -__webpack_modules__[require.resolveWeak(`./page/${page}`)]; -``` - -T> `require.resolveWeak` is the foundation of _universal rendering_ (SSR + Code Splitting), as used in packages such as [react-universal-component](https://github.com/faceyspacey/react-universal-component). It allows code to render synchronously on both the server and initial page-loads on the client. It requires that chunks are manually served or somehow available. It's able to require modules without indicating they should be bundled into a chunk. It's used in conjunction with `import()` which takes over when user navigation triggers additional imports. - - -# Node.js API - -webpack provides a Node.js API which can be used directly in Node.js runtime. - -The Node.js API is useful in scenarios in which you need to customize the build or development process since all the reporting and error handling must be done manually and webpack only does the compiling part. For this reason the [`stats`](/configuration/stats) configuration options will not have any effect in the `webpack()` call. - - -## Installation - -To start using webpack Node.js API, first install webpack if you haven’t yet: - -``` bash -npm install --save-dev webpack -``` - -Then require the webpack module in your Node.js script: - -``` js -const webpack = require('webpack'); -``` - -Or if you prefer ES2015: - -``` js -import webpack from 'webpack'; -``` - - -## `webpack()` - -The imported `webpack` function is fed a webpack [Configuration Object](/configuration/) and runs the webpack compiler if a callback function is provided: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, [stats](#stats-object)) => { - if (err || stats.hasErrors()) { - // [Handle errors here](#error-handling) - } - // Done processing -}); -``` - -T> The `err` object __will not__ include compilation errors and those must be handled separately using `stats.hasErrors()` which will be covered in detail in [Error Handling](#error-handling) section of this guide. The `err` object will only contain webpack-related issues, such as misconfiguration, etc. - -T> You can provide the `webpack` function with an array of configurations. See -the [MultiCompiler](#multicompiler) section below for more information. - - -## Compiler Instance - -If you don’t pass the `webpack` runner function a callback, it will return a -webpack `Compiler` instance. This instance can be used to manually trigger the -webpack runner or have it build and watch for changes, much like the -[CLI](/api/cli/). The `Compiler` instance provides the following methods: - -- `.run(callback)` -- `.watch(watchOptions, handler)` - -Typically, only one master `Compiler` instance is created, although child -compilers can be created in order to delegate specific tasks. The `Compiler` is -ultimately just a function which performs bare minimum functionality to keep a -lifecycle running. It delegates all the loading, bundling, and writing work to -registered plugins. - -The `hooks` property on a `Compiler` instance is used to register a plugin to -any hook event in the `Compiler`'s lifecycle. The -[`WebpackOptionsDefaulter`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js) -and [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js) -utilities are used by webpack to configure its `Compiler` instance with all the -built-in plugins. - -The `run` method is then used to kickstart all compilation work. Upon -completion, the given `callback` function is executed. The final logging of -stats and errors should be done in this `callback` function. - -W> The API only supports a single concurrent compilation at a time. When using -`run`, wait for it to finish before calling `run` or `watch` again. When using -`watch`, call `close` and wait for it to finish before calling `run` or `watch` -again. Concurrent compilations will corrupt the output files. - - -## Run - -Calling the `run` method on the `Compiler` instance is much like the quick run -method mentioned above: - -``` js-with-links -const webpack = require("webpack"); - -const compiler = webpack({ - // [Configuration Object](/configuration/) -}); - -compiler.run((err, [stats](#stats-object)) => { - // ... -}); -``` - - -## Watching - -Calling the `watch` method, triggers the webpack runner, but then watches for -changes (much like CLI: `webpack --watch`), as soon as webpack detects a -change, runs again. Returns an instance of `Watching`. - -``` js -watch(watchOptions, callback); -``` - -``` js-with-links -const webpack = require("webpack"); - -const compiler = webpack({ - // [Configuration Object](/configuration/) -}); - -const watching = compiler.watch({ - // Example [watchOptions](/configuration/watch/#watchoptions) - aggregateTimeout: 300, - poll: undefined -}, (err, [stats](#stats-object)) => { - // Print watch/build result here... - console.log(stats); -}); -``` - -`Watching` options are covered in detail -[here](/configuration/watch/#watchoptions). - -W> Filesystem inaccuracies may trigger multiple builds for a single change. So, -in the example above, the `console.log` statement may fire multiple times for a -single modification. Users should expect this behavior and may check -`stats.hash` to see if the file hash has actually changed. - - -### Close `Watching` - -The `watch` method returns a `Watching` instance that exposes -`.close(callback)` method. Calling this method will end watching: - -``` js -watching.close(() => { - console.log('Watching Ended.'); -}); -``` - -W> It’s not allowed to watch or run again before the existing watcher has been -closed or invalidated. - - -### Invalidate `Watching` - -Using `watching.invalidate`, you can manually invalidate the current compiling -round, without stopping the watch process: - -``` js -watching.invalidate(); -``` - - -## Stats Object - -The `stats` object that is passed as a second argument of the -[`webpack()`](#webpack-) callback, is a good source of information about the -code compilation process. It includes: - -- Errors and Warnings (if any) -- Timings -- Module and Chunk information - -The [webpack CLI](/api/cli) uses this information to display nicely formatted -output in your console. - -T> When using the [`MultiCompiler`](/api/plugins/compiler#multicompiler), a -`MultiStats` instance is returned that fulfills the same interface as `stats`, -i.e. the methods described below. - -This `stats` object exposes the following methods: - - -### `stats.hasErrors()` - -Can be used to check if there were errors while compiling. Returns `true` or -`false`. - - -### `stats.hasWarnings()` - -Can be used to check if there were warnings while compiling. Returns `true` or -`false`. - - -### `stats.toJson(options)` - -Returns compilation information as a JSON object. `options` can be either a -string (a preset) or an object for more granular control: - -``` js-with-links -stats.toJson("minimal"); // [more options: "verbose", etc](/configuration/stats). -``` - -``` js -stats.toJson({ - assets: false, - hash: true -}); -``` - -All available options and presets are described in the stats [documentation](/configuration/stats). - -> Here’s an [example] -(https://github.com/webpack/analyse/blob/master/app/pages/upload/example.json) -of this function’s output. - - -### `stats.toString(options)` - -Returns a formatted string of the compilation information (similar to -[CLI](/api/cli) output). - -Options are the same as [`stats.toJson(options)`](/api/node#stats-tojson-options-) with one addition: - -``` js -stats.toString({ - // Add console colors - colors: true -}); -``` - -Here’s an example of `stats.toString()` usage: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, stats) => { - if (err) { - console.error(err); - return; - } - - console.log(stats.toString({ - chunks: false, // Makes the build much quieter - colors: true // Shows colors in the console - })); -}); -``` - - -## MultiCompiler - -The `MultiCompiler` module allows webpack to run multiple configurations in -separate compilers. If the `options` parameter in the webpack's NodeJS api is -an array of options, webpack applies separate compilers and calls the -`callback` method at the end of each compiler execution. - -``` js-with-links -var webpack = require('webpack'); - -webpack([ - { entry: './index1.js', output: { filename: 'bundle1.js' } }, - { entry: './index2.js', output: { filename: 'bundle2.js' } } -], (err, [stats](#stats-object)) => { - process.stdout.write(stats.toString() + "\n"); -}) -``` - -W> Multiple configurations will __not be run in parallel__. Each -configuration is only processed after the previous one has finished -processing. To process them in parallel, you can use a third-party solution -like [parallel-webpack](https://www.npmjs.com/package/parallel-webpack). - - -## Error Handling - -For a good error handling, you need to account for these three types of errors: - -- Fatal webpack errors (wrong configuration, etc) -- Compilation errors (missing modules, syntax errors, etc) -- Compilation warnings - -Here’s an example that does all that: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, stats) => { - if (err) { - console.error(err.stack || err); - if (err.details) { - console.error(err.details); - } - return; - } - - const info = stats.toJson(); - - if (stats.hasErrors()) { - console.error(info.errors); - } - - if (stats.hasWarnings()) { - console.warn(info.warnings); - } - - // Log result... -}); -``` - - -## Custom File Systems - -By default, webpack reads files and writes files to disk using a normal file -system. However, it is possible to change the input or output behavior using a -different kind of file system (memory, webDAV, etc). To accomplish this, one -can change the `inputFileSystem` or `outputFileSystem`. For example, you can -replace the default `outputFileSystem` with -[`memory-fs`](https://github.com/webpack/memory-fs) to write files to memory -instead of to disk: - -``` js -const MemoryFS = require('memory-fs'); -const webpack = require('webpack'); - -const fs = new MemoryFS(); -const compiler = webpack({ /* options*/ }); - -compiler.outputFileSystem = fs; -compiler.run((err, stats) => { - // Read the output later: - const content = fs.readFileSync('...'); -}); -``` - -Note that this is what -[webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware), -used by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) -and many other packages, uses to mysteriously hide your files but continue -serving them up to the browser! - -T> The output file system you provide needs to be compatible with Node’s own -[`fs`](https://nodejs.org/api/fs.html) interface, which requires the `mkdirp` -and `join` helper methods. - - -# Resolvers - -Resolvers are created using the `enhanced-resolve` package. The `Resolver` -class extends the `tapable` class and uses `tapable` to provide a few hooks. -The `enhanced-resolve` package can be used directly to create new resolvers, -however any [`compiler` instance](/api/node/#compiler-instance) has a few resolver instances that can be -tapped into. - -Before reading on, make sure you at least skim through the -[`enhanced-resolve`](https://github.com/webpack/enhanced-resolve) and [`tapable`](/api/plugins/#tapable) documentation. - - -## Types - -There are three types of built-in resolvers available on the `compiler` class: - -- Normal: Resolves a module via an absolute or relative path. -- Context: Resolves a module within a given context. -- Loader: Resolves a webpack [loader](/loaders). - -Depending on need, any one of these built-in resolver used by the `compiler` -can be customized via plugins as such: - -``` js -compiler.resolverFactory.plugin('resolver [type]', resolver => { - resolver.hooks.resolve.tapAsync('MyPlugin', params => { - // ... - }); -}); -``` - -Where `[type]` is one of the three resolvers mention above, specified as: - -- `normal` -- `context` -- `loader` - - -See the `enhanced-resolve` [documentation](https://github.com/webpack/enhanced-resolve) for a full list of hooks and -descriptions. - - -## Configuration Options - -The resolvers mentioned above can also be customized via a configuration file -with the [`resolve`](/configuration/resolve/) or [`resolveLoader`](/configuration/resolve/#resolveloader) options. These options allow -users to change the resolving behavior through a variety of options including -through resolve `plugins`. - -The resolver plugins, e.g. [`DirectoryNamedPlugin`](https://github.com/shaketbaby/directory-named-webpack-plugin), can be included -directly in `resolve.plugins` rather than using standard plugins. Note that the -`resolve` configuration affects the `normal` and `context` resolvers while -`resolveLoader` is used to modify the `loader` resolver. - - -# Stats Data - -When compiling source code with webpack, users can generate a JSON file containing statistics about modules. These statistics can be used to analyze an application's dependency graph as well as to optimize compilation speed. The file is typically generated with the following CLI command: - -``` bash -webpack --profile --json > compilation-stats.json -``` - -The `--json > compilation-stats.json` flag indicates to webpack that it should emit the `compilation-stats.json` containing the dependency graph and various other build information. Typically, the `--profile` flag is also added so that a `profile` section is added to each [`modules` object](#module-objects) containing module-specific compilation stats. - - -## Structure - -The top-level structure of the output JSON file is fairly straightforward but there are a few nested data structures as well. Each nested structure has a dedicated section below to make this document more consumable. Note that you can click links within the top-level structure below to jump to relevant sections and documentation: - -```js-with-links -{ - "version": "1.4.13", // Version of webpack used for the compilation - "hash": "11593e3b3ac85436984a", // Compilation specific hash - "time": 2469, // Compilation time in milliseconds - "filteredModules": 0, // A count of excluded modules when [`exclude`](/configuration/stats/#stats) is passed to the [`toJson`](/api/node/#stats-tojson-options-) method - "outputPath": "/", // path to webpack output directory - "assetsByChunkName": { - // Chunk name to emitted asset(s) mapping - "main": "web.js?h=11593e3b3ac85436984a", - "named-chunk": "named-chunk.web.js", - "other-chunk": [ - "other-chunk.js", - "other-chunk.css" - ] - }, - "assets": [ - // A list of [asset objects](#asset-objects) - ], - "chunks": [ - // A list of [chunk objects](#chunk-objects) - ], - "modules": [ - // A list of [module objects](#module-objects) - ], - "errors": [ - // A list of [error strings](#errors-and-warnings) - ], - "warnings": [ - // A list of [warning strings](#errors-and-warnings) - ] -} -``` - - -### Asset Objects - -Each `assets` object represents an `output` file emitted from the compilation. They all follow a similar structure: - -<!-- eslint-skip --> - -```js -{ - "chunkNames": [], // The chunks this asset contains - "chunks": [ 10, 6 ], // The chunk IDs this asset contains - "emitted": true, // Indicates whether or not the asset made it to the `output` directory - "name": "10.web.js", // The `output` filename - "size": 1058 // The size of the file in bytes -} -``` - - -### Chunk Objects - -Each `chunks` object represents a group of modules known as a [chunk](/glossary#c). Each object follows the following structure: - -```js-with-links -{ - "entry": true, // Indicates whether or not the chunk contains the webpack runtime - "files": [ - // An array of filename strings that contain this chunk - ], - "filteredModules": 0, // See the description in the [top-level structure](#structure) above - "id": 0, // The ID of this chunk - "initial": true, // Indicates whether this chunk is loaded on initial page load or [on demand](/guides/lazy-loading) - "modules": [ - // A list of [module objects](#module-objects) - "web.js?h=11593e3b3ac85436984a" - ], - "names": [ - // An list of chunk names contained within this chunk - ], - "origins": [ - // See the description below... - ], - "parents": [], // Parent chunk IDs - "rendered": true, // Indicates whether or not the chunk went through Code Generation - "size": 188057 // Chunk size in bytes -} -``` - -The `chunks` object will also contain a list of `origins` describing how the given chunk originated. Each `origins` object follows the following schema: - -```js-with-links -{ - "loc": "", // Lines of code that generated this chunk - "module": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleId": 0, // The ID of the module - "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleName": "./lib/index.web.js", // Relative path to the module - "name": "main", // The name of the chunk - "reasons": [ - // A list of the same `reasons` found in [module objects](#module-objects) - ] -} -``` - - -### Module Objects - -What good would these statistics be without some description of the compiled application's actual modules? Each module in the dependency graph is represented by the following structure: - -```js-with-links -{ - "assets": [ - // A list of [asset objects](#asset-objects) - ], - "built": true, // Indicates that the module went through [Loaders](/concepts/loaders), Parsing, and Code Generation - "cacheable": true, // Whether or not this module is cacheable - "chunks": [ - // IDs of chunks that contain this module - ], - "errors": 0, // Number of errors when resolving or processing the module - "failed": false, // Whether or not compilation failed on this module - "id": 0, // The ID of the module (analagous to [`module.id`](/api/module-variables#module-id-commonjs-)) - "identifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // A unique ID used internally - "name": "./lib/index.web.js", // Path to the actual file - "optional": false, // All requests to this module are with `try... catch` blocks (irrelevant with ESM) - "prefetched": false, // Indicates whether or not the module was [prefetched](/plugins/prefetch-plugin) - "profile": { - // Module specific compilation stats corresponding to the [`--profile` flag](/api/cli#profiling) (in milliseconds) - "building": 73, // Loading and parsing - "dependencies": 242, // Building dependencies - "factory": 11 // Resolving dependencies - }, - "reasons": [ - // See the description below... - ], - "size": 3593, // Estimated size of the module in bytes - "source": "// Should not break it...\r\nif(typeof...", // The stringified raw source - "warnings": 0 // Number of warnings when resolving or processing the module -} -``` - -Every module also contains a list of `reasons` objects describing why that module was included in the dependency graph. Each "reason" is similar to the `origins` seen above in the [chunk objects](#chunk-objects) section: - -```js-with-links -{ - "loc": "33:24-93", // Lines of code that caused the module to be included - "module": "./lib/index.web.js", // Relative path to the module based on [context](/configuration/entry-context/#context) - "moduleId": 0, // The ID of the module - "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleName": "./lib/index.web.js", // A more readable name for the module (used for "pretty-printing") - "type": "require.context", // The [type of request](/api/module-methods) used - "userRequest": "../../cases" // Raw string used for the `import` or `require` request -} -``` - - -### Errors and Warnings - -The `errors` and `warnings` properties each contain a list of strings. Each string contains a message and stack trace: - -``` bash -../cases/parsing/browserify/index.js -Critical dependencies: -2:114-121 This seem to be a pre-built javascript file. Even while this is possible, it's not recommended. Try to require to original source to get better results. - @ ../cases/parsing/browserify/index.js 2:114-121 -``` - -W> Note that the stack traces are removed when `errorDetails: false` is passed to the `toJson` method. The `errorDetails` option is set to `true` by default. - - -# Loader API - -A loader is just a JavaScript module that exports a function. The [loader runner](https://github.com/webpack/loader-runner) calls this function and passes the result of the previous loader or the resource file into it. The `this` context of the function is filled-in by webpack and the [loader runner](https://github.com/webpack/loader-runner) with some useful methods that allow the loader (among other things) to change its invocation style to async, or get query parameters. - -The first loader is passed one argument: the content of the resource file. The compiler expects a result from the last loader. The result should be a `String` or a `Buffer` (which is converted to a string), representing the JavaScript source code of the module. An optional SourceMap result (as JSON object) may also be passed. - -A single result can be returned in __sync mode__. For multiple results the `this.callback()` must be called. In __async mode__ `this.async()` must be called to indicate that the [loader runner](https://github.com/webpack/loader-runner) should wait for an asynchronous result. It returns `this.callback()`. Then the loader must return `undefined` and call that callback. - - -## Examples - -The following sections provide some basic examples of the different types of loaders. Note that the `map` and `meta` parameters are optional, see [`this.callback`](/api/loaders#this-callback) below. - -### Synchronous Loaders - -Either `return` or `this.callback` can be used to return the transformed `content` synchronously: - -__sync-loader.js__ - -``` js -module.exports = function(content, map, meta) { - return someSyncOperation(content); -}; -``` - -The `this.callback` method is more flexible as it allows multiple arguments to be passed as opposed to just the `content`. - -__sync-loader-with-multiple-results.js__ - -``` js -module.exports = function(content, map, meta) { - this.callback(null, someSyncOperation(content), map, meta); - return; // always return undefined when calling callback() -}; -``` - -### Asynchronous Loaders - -For asynchronous loaders, [`this.async`](/api/loaders#this-async) is used to retrieve the `callback` function: - -__async-loader.js__ - -``` js -module.exports = function(content, map, meta) { - var callback = this.async(); - someAsyncOperation(content, function(err, result) { - if (err) return callback(err); - callback(null, result, map, meta); - }); -}; -``` - -__async-loader-with-multiple-results.js__ - -``` js -module.exports = function(content, map, meta) { - var callback = this.async(); - someAsyncOperation(content, function(err, result, sourceMaps, meta) { - if (err) return callback(err); - callback(null, result, sourceMaps, meta); - }); -}; -``` - -T> Loaders were originally designed to work in synchronous loader pipelines, like Node.js (using [enhanced-require](https://github.com/webpack/enhanced-require)), _and_ asynchronous pipelines, like in webpack. However, since expensive synchronous computations are a bad idea in a single-threaded environment like Node.js, we advise to make your loader asynchronously if possible. Synchronous loaders are ok if the amount of computation is trivial. - - -### "Raw" Loader - -By default, the resource file is converted to a UTF-8 string and passed to the loader. By setting the `raw` flag, the loader will receive the raw `Buffer`. Every loader is allowed to deliver its result as `String` or as `Buffer`. The compiler converts them between loaders. - -__raw-loader.js__ - -``` js -module.exports = function(content) { - assert(content instanceof Buffer); - return someSyncOperation(content); - // return value can be a `Buffer` too - // This is also allowed if loader is not "raw" -}; -module.exports.raw = true; -``` - - -### Pitching Loader - -Loaders are __always__ called from right to left. There are some instances where the loader only cares about the __metadata__ behind a request and can ignore the results of the previous loader. The `pitch` method on loaders is called from __left to right__ before the loaders are actually executed (from right to left). For the following [`use`](/configuration/module#rule-use) configuration: - -``` js -module.exports = { - //... - module: { - rules: [ - { - //... - use: [ - 'a-loader', - 'b-loader', - 'c-loader' - ] - } - ] - } -}; -``` - -These steps would occur: - -``` diff -|- a-loader `pitch` - |- b-loader `pitch` - |- c-loader `pitch` - |- requested module is picked up as a dependency - |- c-loader normal execution - |- b-loader normal execution -|- a-loader normal execution -``` - -So why might a loader take advantage of the "pitching" phase? - -First, the `data` passed to the `pitch` method is exposed in the execution phase as well under `this.data` and could be useful for capturing and sharing information from earlier in the cycle. - -``` js -module.exports = function(content) { - return someSyncOperation(content, this.data.value); -}; - -module.exports.pitch = function(remainingRequest, precedingRequest, data) { - data.value = 42; -}; -``` - -Second, if a loader delivers a result in the `pitch` method the process turns around and skips the remaining loaders. In our example above, if the `b-loader`s `pitch` method returned something: - -``` js -module.exports = function(content) { - return someSyncOperation(content); -}; - -module.exports.pitch = function(remainingRequest, precedingRequest, data) { - if (someCondition()) { - return 'module.exports = require(' + JSON.stringify('-!' + remainingRequest) + ');'; - } -}; -``` - -The steps above would be shortened to: - -``` diff -|- a-loader `pitch` - |- b-loader `pitch` returns a module -|- a-loader normal execution -``` - -See the [bundle-loader](https://github.com/webpack-contrib/bundle-loader) for a good example of how this process can be used in a more meaningful way. - - -## The Loader Context - -The loader context represents the properties that are available inside of a loader assigned to the `this` property. - -Given the following example this require call is used: -In `/abc/file.js`: - -``` js -require('./loader1?xyz!loader2!./resource?rrr'); -``` - - -### `this.version` - -__Loader API version.__ Currently `2`. This is useful for providing backwards compatibility. Using the version you can specify custom logic or fallbacks for breaking changes. - - -### `this.context` - -__The directory of the module.__ Can be used as context for resolving other stuff. - -In the example: `/abc` because `resource.js` is in this directory - - -### `this.rootContext` - -Starting with webpack 4, the formerly `this.options.context` is provided as `this.rootContext`. - - -### `this.request` - -The resolved request string. - -In the example: `"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"` - - -### `this.query` - -1. If the loader was configured with an [`options`](/configuration/module/#useentry) object, this will point to that object. -2. If the loader has no `options`, but was invoked with a query string, this will be a string starting with `?`. - -T> Use the [`getOptions` method](https://github.com/webpack/loader-utils#getoptions) from `loader-utils` to extract given loader options. - - -### `this.callback` - -A function that can be called synchronously or asynchronously in order to return multiple results. The expected arguments are: - -<!-- eslint-skip --> - -```js -this.callback( - err: Error | null, - content: string | Buffer, - sourceMap?: SourceMap, - meta?: any -); -``` - -1. The first argument must be an `Error` or `null` -2. The second argument a `string` or a [`Buffer`](https://nodejs.org/api/buffer.html). -3. Optional: The third argument must be a source map that is parsable by [this module](https://github.com/mozilla/source-map). -4. Optional: The fourth option, ignored by webpack, can be anything (e.g. some meta data). - -T> It can be useful to pass an abstract syntax tree (AST), like [`ESTree`](https://github.com/estree/estree), as the fourth argument (`meta`) to speed up the build time if you want to share common ASTs between loaders. - -In case this function is called, you should return undefined to avoid ambiguous loader results. - - -### `this.async` - -Tells the [loader-runner](https://github.com/webpack/loader-runner) that the loader intends to call back asynchronously. Returns `this.callback`. - - -### `this.data` - -A data object shared between the pitch and the normal phase. - - -### `this.cacheable` - -A function that sets the cacheable flag: - -``` typescript -cacheable(flag = true: boolean) -``` - -By default, loader results are flagged as cacheable. Call this method passing `false` to make the loader's result not cacheable. - -A cacheable loader must have a deterministic result, when inputs and dependencies haven't changed. This means the loader shouldn't have other dependencies than specified with `this.addDependency`. - - -### `this.loaders` - -An array of all the loaders. It is writeable in the pitch phase. - -<!-- eslint-skip --> - -```js -loaders = [{request: string, path: string, query: string, module: function}] -``` - -In the example: - -``` js -[ - { - request: '/abc/loader1.js?xyz', - path: '/abc/loader1.js', - query: '?xyz', - module: [Function] - }, - { - request: '/abc/node_modules/loader2/index.js', - path: '/abc/node_modules/loader2/index.js', - query: '', - module: [Function] - } -]; -``` - - -### `this.loaderIndex` - -The index in the loaders array of the current loader. - -In the example: in loader1: `0`, in loader2: `1` - - -### `this.resource` - -The resource part of the request, including query. - -In the example: `"/abc/resource.js?rrr"` - - -### `this.resourcePath` - -The resource file. - -In the example: `"/abc/resource.js"` - - -### `this.resourceQuery` - -The query of the resource. - -In the example: `"?rrr"` - - -### `this.target` - -Target of compilation. Passed from configuration options. - -Example values: `"web"`, `"node"` - - -### `this.webpack` - -This boolean is set to true when this is compiled by webpack. - -T> Loaders were originally designed to also work as Babel transforms. Therefore if you write a loader that works for both, you can use this property to know if there is access to additional loaderContext and webpack features. - - -### `this.sourceMap` - -Should a source map be generated. Since generating source maps can be an expensive task, you should check if source maps are actually requested. - - -### `this.emitWarning` - -``` typescript -emitWarning(warning: Error) -``` - -Emit a warning. - - -### `this.emitError` - -``` typescript -emitError(error: Error) -``` - -Emit an error. - - -### `this.loadModule` - -``` typescript -loadModule(request: string, callback: function(err, source, sourceMap, module)) -``` - -Resolves the given request to a module, applies all configured loaders and calls back with the generated source, the sourceMap and the module instance (usually an instance of [`NormalModule`](https://github.com/webpack/webpack/blob/master/lib/NormalModule.js)). Use this function if you need to know the source code of another module to generate the result. - - -### `this.resolve` - -``` typescript -resolve(context: string, request: string, callback: function(err, result: string)) -``` - -Resolve a request like a require expression. - - -### `this.addDependency` - -``` typescript -addDependency(file: string) -dependency(file: string) // shortcut -``` - -Adds a file as dependency of the loader result in order to make them watchable. For example, [`html-loader`](https://github.com/webpack-contrib/html-loader) uses this technique as it finds `src` and `src-set` attributes. Then, it sets the url's for those attributes as dependencies of the html file that is parsed. - - -### `this.addContextDependency` - -``` typescript -addContextDependency(directory: string) -``` - -Add a directory as dependency of the loader result. - - -### `this.clearDependencies` - -``` typescript -clearDependencies() -``` - -Remove all dependencies of the loader result. Even initial dependencies and these of other loaders. Consider using `pitch`. - - -### `this.emitFile` - -``` typescript -emitFile(name: string, content: Buffer|string, sourceMap: {...}) -``` - -Emit a file. This is webpack-specific. - - -### `this.fs` - -Access to the `compilation`'s `inputFileSystem` property. - - -## Deprecated context properties - -W> The usage of these properties is highly discouraged since we are planning to remove them from the context. They are still listed here for documentation purposes. - - -### `this.exec` - -``` typescript -exec(code: string, filename: string) -``` - -Execute some code fragment like a module. See [this comment](https://github.com/webpack/webpack.js.org/issues/1268#issuecomment-313513988) for a replacement method if needed. - - -### `this.resolveSync` - -``` typescript -resolveSync(context: string, request: string) -> string -``` - -Resolve a request like a require expression. - - -### `this.value` - -Pass values to the next loader. If you know what your result exports if executed as module, set this value here (as a only element array). - - -### `this.inputValue` - -Passed from the last loader. If you would execute the input argument as module, consider reading this variable for a shortcut (for performance). - - -### `this.options` - -W> The `options` property has been deprecated in webpack 3 and removed in webpack 4. - - -### `this.debug` - -A boolean flag. It is set when in debug mode. - - -### `this.minimize` - -Should the result be minimized. - - -### `this._compilation` - -Hacky access to the Compilation object of webpack. - - -### `this._compiler` - -Hacky access to the Compiler object of webpack. - - -### `this._module` - -Hacky access to the Module object being loaded. - - -# Module Variables - -This section covers all __variables__ available in code compiled with webpack. Modules will have access to certain data from the compilation process through `module` and other variables. - - -### `module.loaded` (NodeJS) - -This is `false` if the module is currently executing, and `true` if the sync execution has finished. - - -### `module.hot` (webpack-specific) - -Indicates whether or not [Hot Module Replacement](/concepts/hot-module-replacement) is enabled and provides an interface to the process. See the [HMR API page](/api/hot-module-replacement) for details. - - -### `module.id` (CommonJS) - -The ID of the current module. - -``` javascript -module.id === require.resolve('./file.js'); -``` - - -### `module.exports` (CommonJS) - -Defines the value that will be returned when a consumer makes a `require` call to the module (defaults to a new object). - -``` javascript -module.exports = function doSomething() { - // Do something... -}; -``` - -W> This CANNOT be used in an asynchronous function. - - -### `exports` (CommonJS) - -This variable is equal to default value of `module.exports` (i.e. an object). If `module.exports` gets overwritten, `exports` will no longer be exported. - -``` javascript -exports.someValue = 42; -exports.anObject = { - x: 123 -}; -exports.aFunction = function doSomething() { - // Do something -}; -``` - - -### `global` (NodeJS) - -See [node.js global](https://nodejs.org/api/globals.html#globals_global). - - -### `process` (NodeJS) - -See [node.js process](https://nodejs.org/api/process.html). - - -### `__dirname` (NodeJS) - -Depending on the config option `node.__dirname`: - -- `false`: Not defined -- `mock`: equal "/" -- `true`: [node.js __dirname](https://nodejs.org/api/globals.html#globals_dirname) - -If used inside a expression that is parsed by the Parser, the config option is treated as `true`. - - -### `__filename` (NodeJS) - -Depending on the config option `node.__filename`: - -- `false`: Not defined -- `mock`: equal "/index.js" -- `true`: [node.js __filename](https://nodejs.org/api/globals.html#globals_filename) - -If used inside a expression that is parsed by the Parser, the config option is treated as `true`. - - -### `__resourceQuery` (webpack-specific) - -The resource query of the current module. If the following `require` call were made, then the query string would be available in `file.js`. - -``` javascript -require('file.js?test'); -``` - -__file.js__ - -``` javascript -__resourceQuery === '?test'; -``` - - -### `__webpack_public_path__` (webpack-specific) - -Equals the config options `output.publicPath`. - - -### `__webpack_require__` (webpack-specific) - -The raw require function. This expression isn't parsed by the Parser for dependencies. - - -### `__webpack_chunk_load__` (webpack-specific) - -The internal chunk loading function. Takes two arguments: - -- `chunkId` The id for the chunk to load. -- `callback(require)` A callback function called once the chunk is loaded. - - -### `__webpack_modules__` (webpack-specific) - -Access to the internal object of all modules. - - -### `__webpack_hash__` (webpack-specific) - -This variable is only available with the `HotModuleReplacementPlugin` or the `ExtendedAPIPlugin`. It provides access to the hash of the compilation. - - -### `__non_webpack_require__` (webpack-specific) - -Generates a `require` function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available. - - -### `DEBUG` (webpack-specific) - -Equals the config option `debug`. - - -# Parser - -The `parser` instance, found in the `compiler`, is used to parse each module -being processed by webpack. The `parser` is yet another webpack class that -extends `tapable` and provides a variety of `tapable` hooks that can be used by -plugin authors to customize the parsing process. - -The `parser` is found within [module factories](/api/compiler-hooks/#normalmodulefactory) and therefore takes little -more work to access: - -``` js -compiler.hooks.normalModuleFactory.tap('MyPlugin', factory => { - factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => { - parser.hooks.someHook.tap(/* ... */); - }); -}); -``` - -As with the `compiler`, `tapAsync` and `tapPromise` may also be available -depending on the type of hook. - - -## Hooks - -The following lifecycle hooks are exposed by the `parser` and can be accessed -as such: - - -### evaluateTypeof - -`SyncBailHook` - -Evaluate the type of an identifier. - -Parameters: `expression` - - -### evaluate - -`SyncBailHook` - -Evaluate an expression. - -Parameters: `expression` - - -### evaluateIdentifier - -`SyncBailHook` - -Evaluate an identifier that is a free variable. - -Parameters: `expression` - - -### evaluateDefinedIdentifier - -`SyncBailHook` - -Evaluate an identifier that is a defined variable. - -Parameters: `expression` - - -### evaluateCallExpressionMember - -`SyncBailHook` - -Evaluate a call to a member function of a successfully evaluated expression. - -Parameters: `expression` `param` - - -### statement - -`SyncBailHook` - -General purpose hook that is called when parsing statements in a code fragment. - -Parameters: `statement` - - -### statementIf - -`SyncBailHook` - -... - -Parameters: `statement` - - -### label - -`SyncBailHook` - -... - -Parameters: `statement` - - -### import - -`SyncBailHook` - -... - -Parameters: `statement` `source` - - -### importSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `source` `exportName` `identifierName` - - -### export - -`SyncBailHook` - -... - -Parameters: `statement` - - -### exportImport - -`SyncBailHook` - -... - -Parameters: `statement` `source` - - -### exportDeclaration - -`SyncBailHook` - -... - -Parameters: `statement` `declaration` - - -### exportExpression - -`SyncBailHook` - -... - -Parameters: `statement` `declaration` - - -### exportSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `identifierName` `exportName` `index` - - -### exportImportSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `source` `identifierName` `exportName` `index` - - -### varDeclaration - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationLet - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationConst - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationVar - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### canRename - -`SyncBailHook` - -... - -Parameters: `initExpression` - - -### rename - -`SyncBailHook` - -... - -Parameters: `initExpression` - - -### assigned - -`SyncBailHook` - -... - -Parameters: `expression` - - -### assign - -`SyncBailHook` - -... - -Parameters: `expression` - - -### typeof - -`SyncBailHook` - -... - -Parameters: `expression` - - -### call - -`SyncBailHook` - -... - -Parameters: `expression` - - -### callAnyMember - -`SyncBailHook` - -... - -Parameters: `expression` - - -### new - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expression - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expressionAnyMember - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expressionConditionalOperator - -`SyncBailHook` - -... - -Parameters: `expression` - - -### program - -`SyncBailHook` - -Get access to the abstract syntax tree (AST) of a code fragment - -Parameters: `ast` `comments` diff --git a/src/content/concepts/_concepts_all.md b/src/content/concepts/_concepts_all.md deleted file mode 100644 index 7ea61cfe8aaa..000000000000 --- a/src/content/concepts/_concepts_all.md +++ /dev/null @@ -1,1086 +0,0 @@ - - -# Concepts - -At its core, __webpack__ is a _static module bundler_ for modern JavaScript applications. When webpack processes your application, it internally builds a [dependency graph](/concepts/dependency-graph/) which maps every module your project needs and generates one or more _bundles_. - -T> Learn more about JavaScript modules and webpack modules [here](/concepts/modules). - -Since version 4.0.0, __webpack does not require a configuration file__ to bundle your project, nevertheless it is [incredibly configurable](/configuration) to better fit your needs. - -To get started you only need to understand its __Core Concepts__: - -- [Entry](#entry) -- [Output](#output) -- [Loaders](#loaders) -- [Plugins](#plugins) -- [Mode](#mode) -- [Browser Compatibility](#browser-compatibility) - -This document is intended to give a __high-level__ overview of these concepts, while providing links to detailed concept specific use cases. - -For a better understanding of the ideas behind module bundlers and how they work under the hood consult these resources: - -- [Manually Bundling an Application](https://www.youtube.com/watch?v=UNMkLHzofQI) -- [Live Coding a Simple Module Bundler](https://www.youtube.com/watch?v=Gc9-7PBqOC8) -- [Detailed Explanation of a Simple Module Bundler](https://github.com/ronami/minipack) - - -## Entry - -An __entry point__ indicates which module webpack should use to begin building out its internal [dependency graph](/concepts/dependency-graph/). webpack will figure out which other modules and libraries that entry point depends on (directly and indirectly). - -By default its value is `./src/index.js`, but you can specify a different (or multiple entry points) by configuring the __entry__ property in the [webpack configuration](/configuration). For example: - -__webpack.config.js__ - -``` js -module.exports = { - entry: './path/to/my/entry/file.js' -}; -``` - -T> Learn more in the [entry points](/concepts/entry-points) section. - - -## Output - -The __output__ property tells webpack where to emit the _bundles_ it creates and how to name these files. It defaults to `./dist/main.js` for the main output file and to the `./dist` folder for any other generated file. - -You can configure this part of the process by specifying an `output` field in your configuration: - -__webpack.config.js__ - -```javascript -const path = require('path'); - -module.exports = { - entry: './path/to/my/entry/file.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'my-first-webpack.bundle.js' - } -}; -``` - -In the example above, we use the `output.filename` and the `output.path` properties to tell webpack the name of our bundle and where we want it to be emitted to. In case you're wondering about the path module being imported at the top, it is a core [Node.js module](https://nodejs.org/api/modules.html) that gets used to manipulate file paths. - -T> The `output` property has [many more configurable features](/configuration/output) and if you like to know more about the concepts behind it, you can [read more in the output section](/concepts/output). - - -## Loaders - -Out of the box, webpack only understands JavaScript and JSON files. __Loaders__ allow webpack to process other types of files and convert them into valid [modules](/concepts/modules) that can be consumed by your application and added to the dependency graph. - -W> Note that the ability to `import` any type of module, e.g. `.css` files, is a feature specific to webpack and may not be supported by other bundlers or task runners. We feel this extension of the language is warranted as it allows developers to build a more accurate dependency graph. - -At a high level, __loaders__ have two properties in your webpack configuration: - -1. The `test` property identifies which file or files should be transformed. -2. The `use` property indicates which loader should be used to do the transforming. - -__webpack.config.js__ - -```javascript -const path = require('path'); - -module.exports = { - output: { - filename: 'my-first-webpack.bundle.js' - }, - module: { - rules: [ - { test: /\.txt$/, use: 'raw-loader' } - ] - } -}; -``` - -The configuration above has defined a `rules` property for a single module with two required properties: `test` and `use`. This tells webpack's compiler the following: - -> "Hey webpack compiler, when you come across a path that resolves to a '.txt' file inside of a `require()`/`import` statement, __use__ the `raw-loader` to transform it before you add it to the bundle." - -W> It is important to remember that when defining rules in your webpack config, you are defining them under `module.rules` and not `rules`. For your benefit, webpack will warn you if this is done incorrectly. - -You can check further customization when including loaders in the [loaders section](/concepts/loaders). - - -## Plugins - -While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables. - -T> Check out the [plugin interface](/api/plugins) and how to use it to extend webpacks capabilities. - -In order to use a plugin, you need to `require()` it and add it to the `plugins` array. Most plugins are customizable through options. Since you can use a plugin multiple times in a config for different purposes, you need to create an instance of it by calling it with the `new` operator. - -__webpack.config.js__ - -```javascript -const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm -const webpack = require('webpack'); //to access built-in plugins - -module.exports = { - module: { - rules: [ - { test: /\.txt$/, use: 'raw-loader' } - ] - }, - plugins: [ - new HtmlWebpackPlugin({template: './src/index.html'}) - ] -}; -``` - -In the example above, the `html-webpack-plugin` generates an HTML file for your application by injecting automatically all your generated bundles. - -T> There are many plugins that webpack provides out of the box! Check out the [list of plugins](/plugins). - -Using plugins in your webpack config is straightforward - however, there are many use cases that are worth further exploration. [Learn more about them here](/concepts/plugins). - - -## Mode - -By setting the `mode` parameter to either `development`, `production` or `none`, you can enable webpack's built-in optimizations that correspond to each environment. The default value is `production`. - -```javascript -module.exports = { - mode: 'production' -}; -``` - -Learn more about the [mode configuration here](/concepts/mode) and what optimizations take place on each value. - - -## Browser Compatibility - -webpack supports all browsers that are [ES5-compliant](https://kangax.github.io/compat-table/es5/) (IE8 and below are not supported). webpack needs `Promise` for `import()` and `require.ensure()`. If you want to support older browsers, you will need to [load a polyfill](/guides/shimming/) before using these expressions. - - -# Entry Points - -As mentioned in [Getting Started](/guides/getting-started/#using-a-configuration), there are multiple ways to define the `entry` property in your webpack configuration. We will show you the ways you __can__ configure the `entry` property, in addition to explaining why it may be useful to you. - - -## Single Entry (Shorthand) Syntax - -Usage: `entry: string|Array<string>` - -__webpack.config.js__ - -```javascript -module.exports = { - entry: './path/to/my/entry/file.js' -}; -``` - -The single entry syntax for the `entry` property is a shorthand for: - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - main: './path/to/my/entry/file.js' - } -}; -``` - -T> __What happens when you pass an array to `entry`?__ Passing an array of file paths to the `entry` property creates what is known as a __"multi-main entry"__. This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk". - -This is a great choice when you are looking to quickly setup a webpack configuration for an application or tool with one entry point (i.e., a library). However, there is not much flexibility in extending or scaling your configuration with this syntax. - - -## Object Syntax - -Usage: `entry: {[entryChunkName: string]: string|Array<string>}` - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - app: './src/app.js', - adminApp: './src/adminApp.js' - } -}; -``` - -The object syntax is more verbose. However, this is the most scalable way of defining entry/entries in your application. - -T> __"Scalable webpack configurations"__ are ones that can be reused and combined with other partial configurations. This is a popular technique used to separate concerns by environment, build target and runtime. They are then merged using specialized tools like [webpack-merge](https://github.com/survivejs/webpack-merge). - - -## Scenarios - -Below is a list of entry configurations and their real-world use cases: - -### Separate App and Vendor Entries - -T> In webpack version < 4 it was common to add vendors as separate entrypoint to compile it as separate file (in combination with the `CommonsChunkPlugin`). This is discouraged in webpack 4. Instead the `optimization.splitChunks` option takes care of separating vendors and app modules and creating a separate file. __Do not__ create a entry for vendors or other stuff which is not the starting point of execution. - -### Multi Page Application - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - pageOne: './src/pageOne/index.js', - pageTwo: './src/pageTwo/index.js', - pageThree: './src/pageThree/index.js' - } -}; -``` - -__What does this do?__ We are telling webpack that we would like 3 separate dependency graphs (like the above example). - -__Why?__ In a multi-page application, the server is going to fetch a new HTML document for you. The page reloads this new document and assets are redownloaded. However, this gives us the unique opportunity to do multiple things: - -- Use `optimization.splitChunks` to create bundles of shared application code between each page. Multi-page applications that reuse a lot of code/modules between entry points can greatly benefit from these techniques, as the amount of entry points increase. - -T> As a rule of thumb: for each HTML document use exactly one entry point. - - -# Output - -Configuring the `output` configuration options tells webpack how to write the compiled files to disk. Note that, while there can be multiple `entry` points, only one `output` configuration is specified. - - -## Usage - -The minimum requirements for the `output` property in your webpack config is to set its value to an object including the following thing: - -- A `filename` to use for the output file(s). - -__webpack.config.js__ - -```javascript -module.exports = { - output: { - filename: 'bundle.js', - } -}; -``` - -This configuration would output a single `bundle.js` file into the `dist` directory. - - -## Multiple Entry Points - -If your configuration creates more than a single "chunk" (as with multiple entry points or when using plugins like CommonsChunkPlugin), you should use [substitutions](/configuration/output#output-filename) to ensure that each file has a unique name. - -```javascript -module.exports = { - entry: { - app: './src/app.js', - search: './src/search.js' - }, - output: { - filename: '[name].js', - path: __dirname + '/dist' - } -}; - -// writes to disk: ./dist/app.js, ./dist/search.js -``` - - -## Advanced - -Here's a more complicated example of using a CDN and hashes for assets: - -__config.js__ - -```javascript -module.exports = { - //... - output: { - path: '/home/proj/cdn/assets/[hash]', - publicPath: 'http://cdn.example.com/assets/[hash]/' - } -}; -``` - -In cases where the eventual `publicPath` of output files isn't known at compile time, it can be left blank and set dynamically at runtime via the `__webpack_public_path__` variable in the entry point file: - -```javascript -__webpack_public_path__ = myRuntimePublicPath; - -// rest of your application entry -``` - - -# Loaders - -Loaders are transformations that are applied on the source code of a module. They allow you to pre-process files as you `import` or “load” them. Thus, loaders are kind of like “tasks” in other build tools and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript or inline images as data URLs. Loaders even allow you to do things like `import` CSS files directly from your JavaScript modules! - - -## Example - -For example, you can use loaders to tell webpack to load a CSS file or to convert TypeScript to JavaScript. To do this, you would start by installing the loaders you need: - -``` bash -npm install --save-dev css-loader -npm install --save-dev ts-loader -``` - -And then instruct webpack to use the [`css-loader`](/loaders/css-loader) for every `.css` file and the [`ts-loader`](https://github.com/TypeStrong/ts-loader) for all `.ts` files: - -__webpack.config.js__ - -``` js -module.exports = { - module: { - rules: [ - { test: /\.css$/, use: 'css-loader' }, - { test: /\.ts$/, use: 'ts-loader' } - ] - } -}; -``` - - -## Using Loaders - -There are three ways to use loaders in your application: - -- [Configuration](#configuration) (recommended): Specify them in your __webpack.config.js__ file. -- [Inline](#inline): Specify them explicitly in each `import` statement. -- [CLI](#cli): Specify them within a shell command. - - -### Configuration - -[`module.rules`](/configuration/module/#module-rules) allows you to specify several loaders within your webpack configuration. -This is a concise way to display loaders, and helps to maintain clean code. It also offers you a full overview of each respective loader. - -Loaders are evaluated/executed from right to left. In the example below execution starts with sass-loader, continues with css-loader and finally ends with style-loader. See ["Loader Features"](/concepts/loaders/#loader-features) for more information about loaders order. - -```js-with-links-with-details -module.exports = { - module: { - rules: [ - { - test: /\.css$/, - use: [ - { loader: ['style-loader'](/loaders/style-loader) }, - { - loader: ['css-loader'](/loaders/css-loader), - options: { - modules: true - } - }, - { loader: ['sass-loader'](/loaders/sass-loader) } - ] - } - ] - } -}; -``` - - -### Inline - -It's possible to specify loaders in an `import` statement, or any [equivalent "importing" method](/api/module-methods). Separate loaders from the resource with `!`. Each part is resolved relative to the current directory. - -```js -import Styles from 'style-loader!css-loader?modules!./styles.css'; -``` - -It's possible to override any loaders in the configuration by prefixing the entire rule with `!`. - -Options can be passed with a query parameter, e.g. `?key=value&foo=bar`, or a JSON object, e.g. `?{"key":"value","foo":"bar"}`. - -T> Use `module.rules` whenever possible, as this will reduce boilerplate in your source code and allow you to debug or locate a loader faster if something goes south. - - -### CLI - -You can also use loaders through the CLI: - -```sh -webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader' -``` - -This uses the `jade-loader` for `.jade` files, and the [`style-loader`](/loaders/style-loader) and [`css-loader`](/loaders/css-loader) for `.css` files. - - -## Loader Features - -- Loaders can be chained. Each loader in the chain applies transformations to the processed resource. A chain is executed in reverse order. The first loader passes its result (resource with applied transformations) to the next one, and so forth. Finally, webpack expects JavaScript to be returned by the last loader in the chain. -- Loaders can be synchronous or asynchronous. -- Loaders run in Node.js and can do everything that’s possible there. -- Loaders can be configured with an `options` object (using `query` parameters to set options is still supported but has been deprecated). -- Normal modules can export a loader in addition to the normal `main` via `package.json` with the `loader` field. -- Plugins can give loaders more features. -- Loaders can emit additional arbitrary files. - -Loaders allow more power in the JavaScript ecosystem through preprocessing -functions (loaders). Users now have more flexibility to include fine-grained logic such as compression, packaging, language translations and [more](/loaders). - - -## Resolving Loaders - -Loaders follow the standard [module resolution](/concepts/module-resolution/). In most cases it will be loaded from the [module path](/concepts/module-resolution/#module-paths) (think `npm install`, `node_modules`). - -A loader module is expected to export a function and be written in Node.js compatible JavaScript. They are most commonly managed with npm, but you can also have custom loaders as files within your application. By convention, loaders are usually named `xxx-loader` (e.g. `json-loader`). See ["How to Write a Loader?"](/development/how-to-write-a-loader) for more information. - - -# Mode - -Providing the `mode` configuration option tells webpack to use its built-in optimizations accordingly. - -`string` - -T> Possible values for `mode` are: `none`, `development` or `production`(default). - -## Usage - -Just provide the `mode` option in the config: - -```javascript -module.exports = { - mode: 'production' -}; -``` - - -or pass it as a [CLI](/api/cli/) argument: - -```bash -webpack --mode=production -``` - -The following string values are supported: - -Option | Description ---------------------- | ----------------------- -`development` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `development`. Enables `NamedChunksPlugin` and `NamedModulesPlugin`. -`production` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `production`. Enables `FlagDependencyUsagePlugin`, `FlagIncludedChunksPlugin`, `ModuleConcatenationPlugin`, `NoEmitOnErrorsPlugin`, `OccurrenceOrderPlugin`, `SideEffectsFlagPlugin` and `TerserPlugin`. -`none` | Opts out of any default optimization options - -If not set, webpack sets `production` as the default value for `mode`. The supported values for mode are: - -T> Please remember that setting `NODE_ENV` doesn't automatically set `mode`. - - -### Mode: development - - -```diff -// webpack.development.config.js -module.exports = { -+ mode: 'development' -- devtool: 'eval', -- cache: true, -- performance: { -- hints: false -- }, -- output: { -- pathinfo: true -- }, -- optimization: { -- namedModules: true, -- namedChunks: true, -- nodeEnv: 'development', -- flagIncludedChunks: false, -- occurrenceOrder: false, -- sideEffects: false, -- usedExports: false, -- concatenateModules: false, -- splitChunks: { -- hidePathInfo: false, -- minSize: 10000, -- maxAsyncRequests: Infinity, -- maxInitialRequests: Infinity, -- }, -- noEmitOnErrors: false, -- checkWasmTypes: false, -- minimize: false, -- }, -- plugins: [ -- new webpack.NamedModulesPlugin(), -- new webpack.NamedChunksPlugin(), -- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), -- ] -} -``` - - -### Mode: production - - -```diff -// webpack.production.config.js -module.exports = { -+ mode: 'production', -- performance: { -- hints: 'warning' -- }, -- output: { -- pathinfo: false -- }, -- optimization: { -- namedModules: false, -- namedChunks: false, -- nodeEnv: 'production', -- flagIncludedChunks: true, -- occurrenceOrder: true, -- sideEffects: true, -- usedExports: true, -- concatenateModules: true, -- splitChunks: { -- hidePathInfo: true, -- minSize: 30000, -- maxAsyncRequests: 5, -- maxInitialRequests: 3, -- }, -- noEmitOnErrors: true, -- checkWasmTypes: true, -- minimize: true, -- }, -- plugins: [ -- new TerserPlugin(/* ... */), -- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), -- new webpack.optimize.ModuleConcatenationPlugin(), -- new webpack.NoEmitOnErrorsPlugin() -- ] -} -``` - - -### Mode: none - - -```diff -// webpack.custom.config.js -module.exports = { -+ mode: 'none', -- performance: { -- hints: false -- }, -- optimization: { -- flagIncludedChunks: false, -- occurrenceOrder: false, -- sideEffects: false, -- usedExports: false, -- concatenateModules: false, -- splitChunks: { -- hidePathInfo: false, -- minSize: 10000, -- maxAsyncRequests: Infinity, -- maxInitialRequests: Infinity, -- }, -- noEmitOnErrors: false, -- checkWasmTypes: false, -- minimize: false, -- }, -- plugins: [] -} -``` - -If you want to change the behavior according to the __mode__ variable inside the _webpack.config.js_, you have to export a function instead of an object: - -```javascript -var config = { - entry: './app.js' - //... -}; - -module.exports = (env, argv) => { - - if (argv.mode === 'development') { - config.devtool = 'source-map'; - } - - if (argv.mode === 'production') { - //... - } - - return config; -}; -``` - - -# Plugins - -__Plugins__ are the [backbone](https://github.com/webpack/tapable) of webpack. webpack itself is built on the __same plugin system__ that you use in your webpack configuration! - -They also serve the purpose of doing __anything else__ that a [loader](/concepts/loaders) cannot do. - - -## Anatomy - -A webpack __plugin__ is a JavaScript object that has an [`apply`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) method. This `apply` method is called by the webpack compiler, giving access to the __entire__ compilation lifecycle. - -__ConsoleLogOnBuildWebpackPlugin.js__ - -```javascript -const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; - -class ConsoleLogOnBuildWebpackPlugin { - apply(compiler) { - compiler.hooks.run.tap(pluginName, compilation => { - console.log('The webpack build process is starting!!!'); - }); - } -} -``` - -The first parameter of the tap method of the compiler hook should be a camelized version of the plugin name. It is advisable to use a constant for this so it can be reused in all hooks. - -## Usage - -Since __plugins__ can take arguments/options, you must pass a `new` instance to the `plugins` property in your webpack configuration. - -Depending on how you are using webpack, there are multiple ways to use plugins. - - -### Configuration - -__webpack.config.js__ - -```javascript -const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm -const webpack = require('webpack'); //to access built-in plugins -const path = require('path'); - -module.exports = { - entry: './path/to/my/entry/file.js', - output: { - filename: 'my-first-webpack.bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.(js|jsx)$/, - use: 'babel-loader' - } - ] - }, - plugins: [ - new webpack.ProgressPlugin(), - new HtmlWebpackPlugin({template: './src/index.html'}) - ] -}; -``` - - -### Node API - -When using the Node API, you can also pass plugins via the `plugins` property in the configuration. - -__some-node-script.js__ - -```javascript -const webpack = require('webpack'); //to access webpack runtime -const configuration = require('./webpack.config.js'); - -let compiler = webpack(configuration); - -new webpack.ProgressPlugin().apply(compiler); - -compiler.run(function(err, stats) { - // ... -}); -``` - -T> Did you know: The example seen above is extremely similar to the [webpack runtime itself!](https://github.com/webpack/webpack/blob/e7087ffeda7fa37dfe2ca70b5593c6e899629a2c/bin/webpack.js#L290-L292) There are lots of great usage examples hiding in the [webpack source code](https://github.com/webpack/webpack) that you can apply to your own configurations and scripts! - - -# Configuration - -You may have noticed that few webpack configurations look exactly alike. This is because __webpack's configuration file is a JavaScript file that exports a webpack [configuration](/configuration/).__ This configuration is then processed by webpack based upon its defined properties. - -Because it's a standard Node.js CommonJS module, you __can do the following__: - -- import other files via `require(...)` -- use utilities on npm via `require(...)` -- use JavaScript control flow expressions i. e. the `?:` operator -- use constants or variables for often used values -- write and execute functions to generate a part of the configuration - -Use these features when appropriate. - -While they are technically feasible, __the following practices should be avoided__: - -- Access CLI arguments, when using the webpack CLI (instead write your own CLI, or [use `--env`](/configuration/configuration-types/)) -- Export non-deterministic values (calling webpack twice should result in the same output files) -- Write long configurations (instead split the configuration into multiple files) - -T> The most important part to take away from this document is that there are many different ways to format and style your webpack configuration. The key is to stick with something consistent that you and your team can understand and maintain. - -The examples below describe how webpack's configuration can be both expressive and configurable because _it is code_: - -## Simple Configuration - -__webpack.config.js__ - -```javascript -var path = require('path'); - -module.exports = { - mode: 'development', - entry: './foo.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'foo.bundle.js' - } -}; -``` - -_See_: [Configuration section](/configuration/) for the all supported configuration options - -## Multiple Targets - -Along with exporting a single configuration as an object, [function](/configuration/configuration-types/#exporting-a-function) or [Promise](/configuration/configuration-types/#exporting-a-promise), you can export multiple configurations. - -_See_: [Exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) - -## Using other Configuration Languages - -webpack accepts configuration files written in multiple programming and data languages. - -_See_: [Configuration Languages](/configuration/configuration-languages/) - - -# Modules - -In [modular programming](https://en.wikipedia.org/wiki/Modular_programming), developers break programs up into discrete chunks of functionality called a _module_. - -Each module has a smaller surface area than a full program, making verification, debugging, and testing trivial. -Well-written _modules_ provide solid abstractions and encapsulation boundaries, so that each module has a coherent design and a clear purpose within the overall application. - -Node.js has supported modular programming almost since its inception. -On the web, however, support for _modules_ has been slow to arrive. -Multiple tools exist that support modular JavaScript on the web, with a variety of benefits and limitations. -webpack builds on lessons learned from these systems and applies the concept of _modules_ to any file in your project. - -## What is a webpack Module - -In contrast to [Node.js modules](https://nodejs.org/api/modules.html), webpack _modules_ can express their _dependencies_ in a variety of ways. A few examples are: - -- An [ES2015 `import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) statement -- A [CommonJS](http://www.commonjs.org/specs/modules/1.0/) `require()` statement -- An [AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md) `define` and `require` statement -- An [`@import` statement](https://developer.mozilla.org/en-US/docs/Web/CSS/@import) inside of a css/sass/less file. -- An image url in a stylesheet (`url(...)`) or html (`<img src=...>`) file. - -T> webpack 1 requires a specific loader to convert ES2015 `import`, however this is possible out of the box via webpack 2 - -## Supported Module Types - -webpack supports modules written in a variety of languages and preprocessors, via _loaders_. _Loaders_ describe to webpack __how__ to process non-JavaScript _modules_ and include these _dependencies_ into your _bundles_. -The webpack community has built _loaders_ for a wide variety of popular languages and language processors, including: - -- [CoffeeScript](http://coffeescript.org) -- [TypeScript](https://www.typescriptlang.org) -- [ESNext (Babel)](https://babeljs.io) -- [Sass](http://sass-lang.com) -- [Less](http://lesscss.org) -- [Stylus](http://stylus-lang.com) - -And many others! Overall, webpack provides a powerful and rich API for customization that allows one to use webpack for __any stack__, while staying __non-opinionated__ about your development, testing, and production workflows. - -For a full list, see [__the list of loaders__](/loaders) or [__write your own__](/api/loaders). - - -# Why webpack - -To understand why you should use webpack let's do a recap of how we used JavaScript on the web before bundlers were a thing. - -There are two ways to run JavaScript in a browser. First, include a script for each functionality you want to implement, the issue is that the solution is hard to scale as loading too many scripts causes a network bottleneck. The other alternative is to load a big .js file containing all your project code, but this results in an unmaintainable scripts that causes problems in scope, size, readability, fragility and monolith files. - - -## IIFE's - Immediately invoked function expressions - -IIFEs solve scoping issues for large projects. When script files are wrapped by an IIFE, you can safely concatenate or safely combine files without concern of scope collision. - -This lead to tools like Make, Gulp, Grunt, Broccoli or Brunch. These tools are known as task runners and they are used, among other purposes, to concatenate all your project files together in order to solve some of the issues mentioned before. - -However, anytime you want to change one file you have to rebuild the whole thing. Concatenating makes it trivial to reuse scripts across files and makes build optimizations more difficult to implement. How do you even know what code is being used and which is not? - -If you are only using one function from lodash or one date utility from moment.js you are actually adding the entire library and just squishing it together. How do you treeshake the dependencies on your code? Also, lazy loading chunks of code can be hard to achieve at scale and requires a lot of manual work from the developer. - - -## Birth of JavaScript Modules happened thanks to Node.js - -webpack runs on Node.js, a JavaScript runtime that can be used in computers and servers outside a browser environment. - -When Node.js was released a new era started, and it came with new challenges. Now that JavaScript is not running in a browser, how are Node applications supposed to load new chunks of code? There are no html files and script tags that can be added to it. - -CommonJS came out and introduced `require`, which allows you to load and use a module in the current file. This solves scope issues out of the box and which code is used becomes clear since we need to import each module that we are going to need. - - -## npm + Node.js + modules -- mass distribution - -JavaScript is taking over the world as a language, as a platform and as a way to rapidly develop and create fast running applications. - -But there is no browser support for CommonJS. There are no [live bindings](https://medium.com/webpack/the-state-of-javascript-modules-4636d1774358). There are problems with circular references. Sync module resolution loader is slow. While CommonJS was a great solution for Node.js projects, browsers didn't support modules. That's when bundlers and tools like Browserify, RequireJS and SystemJS were created to solve this limitation making it possible to write CommonJS modules that run in a browser. - - -## ESM - ECMAScript Modules - -The good news for web projects is that modules are becoming an official feature in ECMAScript standard, though browser support is still short and early implementations show that bundling is still faster and recommended today. - - -## Wouldn't it be nice… - -...to have something that will not only let us write modules but also support any module format (at least until we get to ESM) and that can handle resources and assets at the same time? - -This is why webpack exists. It's a tool that not only let's you bundle your JavaScript applications, supporting both ESM and CommonJS, but can be extended to support all different kinds of assets like images, fonts and stylesheets. - -webpack cares a lot about performance and it's always adding and improving features like async chunk loading and prefetching to help you deliver the best possible version of your project to the user, always caring about loading times and performance. - - -# Module Resolution - -A resolver is a library which helps in locating a module by its absolute path. -A module can be required as a dependency from another module as: - -```js -import foo from 'path/to/module'; -// or -require('path/to/module'); -``` - -The dependency module can be from the application code or a third party library. The resolver helps -webpack find the module code that needs to be included in the bundle for every such `require`/`import` statement. -webpack uses [enhanced-resolve](https://github.com/webpack/enhanced-resolve) to resolve file paths while bundling modules. - - -## Resolving rules in webpack - -Using `enhanced-resolve`, webpack can resolve three kinds of file paths: - - -### Absolute paths - -```js -import '/home/me/file'; - -import 'C:\\Users\\me\\file'; -``` - -Since we already have the absolute path to the file, no further resolution is required. - - -### Relative paths - -```js -import '../src/file1'; -import './file2'; -``` - -In this case, the directory of the resource file where the `import` or `require` occurs is taken to be the context directory. The relative path specified in the `import/require` is joined to this context path to produce the absolute path to the module. - - -### Module paths - -```js -import 'module'; -import 'module/lib/file'; -``` - -Modules are searched for inside all directories specified in [`resolve.modules`](/configuration/resolve/#resolve-modules). -You can replace the original module path by an alternate path by creating an alias for it using [`resolve.alias`](/configuration/resolve/#resolve-alias) configuration option. - -Once the path is resolved based on the above rule, the resolver checks to see if the path points to a file or a directory. If the path points to a file: - -- If the path has a file extension, then the file is bundled straightaway. -- Otherwise, the file extension is resolved using the [`resolve.extensions`](/configuration/resolve/#resolve-extensions) option, which tells the resolver which extensions (eg - `.js`, `.jsx`) are acceptable for resolution. - -If the path points to a folder, then the following steps are taken to find the right file with the right extension: - -- If the folder contains a `package.json` file, then fields specified in [`resolve.mainFields`](/configuration/resolve/#resolve-mainfields) configuration option are looked up in order, and the first such field in `package.json` determines the file path. -- If there is no `package.json` or if the main fields do not return a valid path, file names specified in the [`resolve.mainFiles`](/configuration/resolve/#resolve-mainfiles) configuration option are looked for in order, to see if a matching filename exists in the imported/required directory . -- The file extension is then resolved in a similar way using the `resolve.extensions` option. - -webpack provides reasonable [defaults](/configuration/resolve) for these options depending on your build target. - - -## Resolving Loaders - -This follows the same rules as those specified for file resolution. But the [`resolveLoader`](/configuration/resolve/#resolveloader) configuration option can be used to have separate resolution rules for loaders. - - -## Caching - -Every filesystem access is cached, so that multiple parallel or serial requests to the same file occur faster. In [watch mode](/configuration/watch/#watch), only modified files are evicted from the cache. If watch mode is off, then the cache gets purged before every compilation. - - -See [Resolve API](/configuration/resolve) to learn more on the configuration options mentioned above. - - -# Dependency Graph - -Any time one file depends on another, webpack treats this as a _dependency_. This allows webpack to take non-code assets, such as images or web fonts, and also provide them as _dependencies_ for your application. - -When webpack processes your application, it starts from a list of modules defined on the command line or in its config file. -Starting from these [_entry points_](/concepts/entry-points/), webpack recursively builds a _dependency graph_ that includes every module your application needs, then bundles all of those modules into a small number of _bundles_ - often, just one - to be loaded by the browser. - -T> Bundling your application is especially powerful for _HTTP/1.1_ clients, as it minimizes the number of times your app has to wait while the browser starts a new request. For _HTTP/2_, you can also use [Code Splitting](/guides/code-splitting/) to achieve best results. - - -# Targets - -Because JavaScript can be written for both server and browser, webpack offers multiple deployment _targets_ that you can set in your webpack [configuration](/configuration). - -W> The webpack `target` property is not to be confused with the `output.libraryTarget` property. For more information see [our guide](/concepts/output/) on the `output` property. - -## Usage - -To set the `target` property, you simply set the target value in your webpack config: - -__webpack.config.js__ - -```javascript -module.exports = { - target: 'node' -}; -``` - -In the example above, using `node` webpack will compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks and not touch any built in modules like `fs` or `path`). - -Each _target_ has a variety of deployment/environment specific additions, support to fit its needs. See what [targets are available](/configuration/target/). - -?>Further expansion for other popular target values - -## Multiple Targets - -Although webpack does __not__ support multiple strings being passed into the `target` property, you can create an isomorphic library by bundling two separate configurations: - -__webpack.config.js__ - -```javascript -const path = require('path'); -const serverConfig = { - target: 'node', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'lib.node.js' - } - //… -}; - -const clientConfig = { - target: 'web', // <=== can be omitted as default is 'web' - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'lib.js' - } - //… -}; - -module.exports = [ serverConfig, clientConfig ]; -``` - -The example above will create a `lib.js` and `lib.node.js` file in your `dist` folder. - -## Resources - -As seen from the options above there are multiple different deployment _targets_ that you can choose from. Below is a list of examples, and resources that you can refer to. - -- __[compare-webpack-target-bundles](https://github.com/TheLarkInn/compare-webpack-target-bundles)__: A great resource for testing and viewing different webpack _targets_. Also great for bug reporting. -- __[Boilerplate of Electron-React Application](https://github.com/chentsulin/electron-react-boilerplate)__: A good example of a build process for electron's main process and renderer process. - -?> Need to find up to date examples of these webpack targets being used in live code or boilerplates. - - -# The Manifest - -In a typical application or site built with webpack, there are three main types of code: - -1. The source code you, and maybe your team, have written. -2. Any third-party library or "vendor" code your source is dependent on. -3. A webpack runtime and __manifest__ that conducts the interaction of all modules. - -This article will focus on the last of these three parts, the runtime and in particular the manifest. - - -## Runtime - -The runtime, along with the manifest data, is basically all the code webpack needs to connect your modularized application while it's running in the browser. It contains the loading and resolving logic needed to connect your modules as they interact. This includes connecting modules that have already been loaded into the browser as well as logic to lazy-load the ones that haven't. - - -## Manifest - -Once your application hits the browser in the form of `index.html` file, some bundles and a variety of other assets required by your application must be loaded and linked somehow. That `/src` directory you meticulously laid out is now bundled, minified and maybe even split into smaller chunks for lazy-loading by webpack's [`optimization`](/configuration/optimization/). So how does webpack manage the interaction between all of your required modules? This is where the manifest data comes in... - -As the compiler enters, resolves, and maps out your application, it keeps detailed notes on all your modules. This collection of data is called the "Manifest" and it's what the runtime will use to resolve and load modules once they've been bundled and shipped to the browser. No matter which [module syntax](/api/module-methods) you have chosen, those `import` or `require` statements have now become `__webpack_require__` methods that point to module identifiers. Using the data in the manifest, the runtime will be able to find out where to retrieve the modules behind the identifiers. - - -## The Problem - -So now you have a little bit of insight about how webpack works behind the scenes. "But, how does this affect me?", you might ask. The simple answer is that most of the time it doesn't. The runtime will do its thing, utilizing the manifest, and everything will appear to just magically work once your application hits the browser. However, if you decide to improve your projects performance by utilizing browser caching, this process will all of a sudden become an important thing to understand. - -By using content hashes within your bundle file names, you can indicate to the browser when the contents of a file has changed thus invalidating the cache. Once you start doing this though, you'll immediately notice some funny behavior. Certain hashes change even when their contents apparently do not. This is caused by the injection of the runtime and manifest which changes every build. - -See [the manifest section](/guides/output-management/#the-manifest) of our _Output management_ guide to learn how to extract the manifest, and read the guides below to learn more about the intricacies of long term caching. - - -# Hot Module Replacement - -Hot Module Replacement (HMR) exchanges, adds, or removes [modules](/concepts/modules/) while an application is running, without a full reload. This can significantly speed up development in a few ways: - -- Retain application state which is lost during a full reload. -- Save valuable development time by only updating what's changed. -- Modifications made to CSS/JS in the source code results in an instant browser update which is almost comparable to changing styles directly in the browser's dev tools. - - -## How It Works - -Let's go through some different viewpoints to understand exactly how HMR works... - -### In the Application - -The following steps allow modules to be swapped in and out of an application: - -1. The application asks the HMR runtime to check for updates. -2. The runtime asynchronously downloads the updates and notifies the application. -3. The application then asks the runtime to apply the updates. -4. The runtime synchronously applies the updates. - -You can set up HMR so that this process happens automatically, or you can choose to require user interaction for updates to occur. - - -### In the Compiler - -In addition to normal assets, the compiler needs to emit an "update" to allow updating from previous version to the new version. The "update" consists of two parts: - -1. The updated [manifest](/concepts/manifest) (JSON) -2. One or more updated chunks (JavaScript) - -The manifest contains the new compilation hash and a list of all updated chunks. Each of these chunks contains the new code for all updated modules (or a flag indicating that the module was removed). - -The compiler ensures that module IDs and chunk IDs are consistent between these builds. It typically stores these IDs in memory (e.g. with [webpack-dev-server](/configuration/dev-server/)), but it's also possible to store them in a JSON file. - - -### In a Module - -HMR is an opt-in feature that only affects modules containing HMR code. One example would be patching styling through the [`style-loader`](https://github.com/webpack-contrib/style-loader). In order for patching to work, the `style-loader` implements the HMR interface; when it receives an update through HMR, it replaces the old styles with the new ones. - -Similarly, when implementing the HMR interface in a module, you can describe what should happen when the module is updated. However, in most cases, it's not mandatory to write HMR code in every module. If a module has no HMR handlers, the update bubbles up. This means that a single handler can update a complete module tree. If a single module from the tree is updated, the entire set of dependencies is reloaded. - -See the [HMR API page](/api/hot-module-replacement) for details on the `module.hot` interface. - - -### In the Runtime - -Here things get a bit more technical... if you're not interested in the internals, feel free to jump to the [HMR API page](/api/hot-module-replacement) or [HMR guide](/guides/hot-module-replacement). - -For the module system runtime, additional code is emitted to track module `parents` and `children`. On the management side, the runtime supports two methods: `check` and `apply`. - -A `check` makes an HTTP request to the update manifest. If this request fails, there is no update available. If it succeeds, the list of updated chunks is compared to the list of currently loaded chunks. For each loaded chunk, the corresponding update chunk is downloaded. All module updates are stored in the runtime. When all update chunks have been downloaded and are ready to be applied, the runtime switches into the `ready` state. - -The `apply` method flags all updated modules as invalid. For each invalid module, there needs to be an update handler in the module or in its parent(s). Otherwise, the invalid flag bubbles up and invalidates parent(s) as well. Each bubble continues until the app's entry point or a module with an update handler is reached (whichever comes first). If it bubbles up from an entry point, the process fails. - -Afterwards, all invalid modules are disposed (via the dispose handler) and unloaded. The current hash is then updated and all `accept` handlers are called. The runtime switches back to the `idle` state and everything continues as normal. - - -## Get Started - -HMR can be used in development as a LiveReload replacement. [webpack-dev-server](/configuration/dev-server/) supports a `hot` mode in which it tries to update with HMR before trying to reload the whole page. See the [Hot Module Replacement guide](/guides/hot-module-replacement) for details. - -T> As with many other features, webpack's power lies in its customizability. There are _many_ ways of configuring HMR depending on the needs of a particular project. However, for most purposes, `webpack-dev-server` is a good fit and will allow you to get started with HMR quickly. diff --git a/src/content/configuration/_configuration_all.md b/src/content/configuration/_configuration_all.md deleted file mode 100644 index a1e52dc062a1..000000000000 --- a/src/content/configuration/_configuration_all.md +++ /dev/null @@ -1,5315 +0,0 @@ - - -# Configuration - -Out of the box, webpack won't require you to use a configuration file. However, it will assume the entry point of your project is `src/index` and will output the result in `dist/main.js` minified and optimized for production. - -Usually your projects will need to extend this functionality, for this you can create a `webpack.config.js` file in the root folder and webpack will automatically use it. - -All the available configuration options are specified below. - -T> New to webpack? Check out our guide to some of webpack's [core concepts](/concepts/) to get started! - -## Options - -Click on the name of each option in the configuration code below to jump to the detailed documentation. Also note that the items with arrows can be expanded to show more examples and, in some cases, more advanced configuration. - -W> Notice that throughout the configuration we use Node's built-in [path module](https://nodejs.org/api/path.html) and prefix it with the [__dirname](https://nodejs.org/docs/latest/api/globals.html#globals_dirname) global. This prevents file path issues between operating systems and allows relative paths to work as expected. See [this section](https://nodejs.org/api/path.html#path_windows_vs_posix) for more info on POSIX vs. Windows paths. - -__webpack.config.js__ - -```js-with-links-with-details -const path = require('path'); - -module.exports = { - <details><summary>[mode](/concepts/mode): "production", // "production" | "development" | "none"</summary> - [mode](/concepts/mode): "production", // enable many optimizations for production builds - [mode](/concepts/mode): "development", // enabled useful tools for development - [mode](/concepts/mode): "none", // no defaults - </details> - // Chosen mode tells webpack to use its built-in optimizations accordingly. - <details><summary>[entry](/configuration/entry-context#entry): "./app/entry", // string | object | array</summary> - [entry](/configuration/entry-context#entry): ["./app/entry1", "./app/entry2"], - [entry](/configuration/entry-context#entry): { - a: "./app/entry-a", - b: ["./app/entry-b1", "./app/entry-b2"] - }, - </details> - // defaults to './src' - // Here the application starts executing - // and webpack starts bundling - [output](/configuration/output): { - // options related to how webpack emits results - [path](/configuration/output#output-path): path.resolve(__dirname, "dist"), // string - // the target directory for all output files - // must be an absolute path (use the Node.js path module) - <details><summary>[filename](/configuration/output#output-filename): "bundle.js", // string</summary> - [filename](/configuration/output#output-filename): "[name].js", // for multiple entry points - [filename](/configuration/output#output-filename): "[chunkhash].js", // for [long term caching](/guides/caching) - </details> - // the filename template for entry chunks - <details><summary>[publicPath](/configuration/output#output-publicpath): "/assets/", // string</summary> - [publicPath](/configuration/output#output-publicpath): "", - [publicPath](/configuration/output#output-publicpath): "https://cdn.example.com/", - </details> - // the url to the output directory resolved relative to the HTML page - [library](/configuration/output#output-library): "MyLibrary", // string, - // the name of the exported library - <details><summary>[libraryTarget](/configuration/output#output-librarytarget): "umd", // universal module definition</summary> - [libraryTarget](/configuration/output#output-librarytarget): "umd2", // universal module definition - [libraryTarget](/configuration/output#output-librarytarget): "commonjs2", // exported with module.exports - [libraryTarget](/configuration/output#output-librarytarget): "commonjs", // exported as properties to exports - [libraryTarget](/configuration/output#output-librarytarget): "amd", // defined with AMD defined method - [libraryTarget](/configuration/output#output-librarytarget): "this", // property set on this - [libraryTarget](/configuration/output#output-librarytarget): "var", // variable defined in root scope - [libraryTarget](/configuration/output#output-librarytarget): "assign", // blind assignment - [libraryTarget](/configuration/output#output-librarytarget): "window", // property set to window object - [libraryTarget](/configuration/output#output-librarytarget): "global", // property set to global object - [libraryTarget](/configuration/output#output-librarytarget): "jsonp", // jsonp wrapper - </details> - // the type of the exported library - <details><summary>/* Advanced output configuration (click to show) */</summary> - [pathinfo](/configuration/output#output-pathinfo): true, // boolean - // include useful path info about modules, exports, requests, etc. into the generated cod - [chunkFilename](/configuration/output#output-chunkfilename): "[id].js", - [chunkFilename](/configuration/output#output-chunkfilename): "[chunkhash].js", // for [long term caching](/guides/caching) - // the filename template for additional chunks - [jsonpFunction](/configuration/output#output-jsonpfunction): "myWebpackJsonp", // string - // name of the JSONP function used to load chunks - [sourceMapFilename](/configuration/output#output-sourcemapfilename): "[file].map", // string - [sourceMapFilename](/configuration/output#output-sourcemapfilename): "sourcemaps/[file].map", // string - // the filename template of the source map location - [devtoolModuleFilenameTemplate](/configuration/output#output-devtoolmodulefilenametemplate): "webpack:///[resource-path]", // string - // the name template for modules in a devtool - [devtoolFallbackModuleFilenameTemplate](/configuration/output#output-devtoolfallbackmodulefilenametemplate): "webpack:///[resource-path]?[hash]", // string - // the name template for modules in a devtool (used for conflicts) - [umdNamedDefine](/configuration/output#output-umdnameddefine): true, // boolean - // use a named AMD module in UMD library - [crossOriginLoading](/configuration/output#output-crossoriginloading): "use-credentials", // enum - [crossOriginLoading](/configuration/output#output-crossoriginloading): "anonymous", - [crossOriginLoading](/configuration/output#output-crossoriginloading): false, - // specifies how cross origin request are issued by the runtime - <details><summary>/* Expert output configuration (on own risk) */</summary> - [devtoolLineToLine](/configuration/output#output-devtoollinetoline): { - test: /\.jsx$/ - }, - // use a simple 1:1 mapped SourceMaps for these modules (faster) - [hotUpdateMainFilename](/configuration/output#output-hotupdatemainfilename): "[hash].hot-update.json", // string - // filename template for HMR manifest - [hotUpdateChunkFilename](/configuration/output#output-hotupdatechunkfilename): "[id].[hash].hot-update.js", // string - // filename template for HMR chunks - [sourcePrefix](/configuration/output#output-sourceprefix): "\t", // string - // prefix module sources in bundle for better readablitity - </details> - </details> - }, - [module](/configuration/module): { - // configuration regarding modules - [rules](/configuration/module#module-rules): [ - // rules for modules (configure loaders, parser options, etc.) - { - [test](/configuration/module#rule-test): /\.jsx?$/, - [include](/configuration/module#rule-include): [ - path.resolve(__dirname, "app") - ], - [exclude](/configuration/module#rule-exclude): [ - path.resolve(__dirname, "app/demo-files") - ], - // these are matching conditions, each accepting a regular expression or string - // test and include have the same behavior, both must be matched - // exclude must not be matched (takes preference over test and include) - // Best practices: - // - Use RegExp only in test and for filename matching - // - Use arrays of absolute paths in include and exclude - // - Try to avoid exclude and prefer include - [issuer](/configuration/module#rule-issuer): { test, include, exclude }, - // conditions for the issuer (the origin of the import) - [enforce](/configuration/module#rule-enforce): "pre", - [enforce](/configuration/module#rule-enforce): "post", - // flags to apply these rules, even if they are overridden (advanced option) - [loader](/configuration/module#rule-loader): "babel-loader", - // the loader which should be applied, it'll be resolved relative to the context - // -loader suffix is no longer optional in webpack2 for clarity reasons - // see [webpack 1 upgrade guide](/migrate/3/#automatic-loader-module-name-extension-removed) - [options](/configuration/module#rule-options-rule-query): { - presets: ["es2015"] - }, - // options for the loader - }, - { - [test](/configuration/module#rule-test): /\.html$/, - [use](/configuration/module#rule-use): [ - // apply multiple loaders and options - "htmllint-loader", - { - loader: "html-loader", - options: { - /* ... */ - } - } - ] - }, - { [oneOf](/configuration/module#rule-oneof): [ /* rules */ ] }, - // only use one of these nested rules - { [rules](/configuration/module#rule-rules): [ /* rules */ ] }, - // use all of these nested rules (combine with conditions to be useful) - { [resource](/configuration/module#rule-resource): { [and](/configuration/module#condition): [ /* conditions */ ] } }, - // matches only if all conditions are matched - { [resource](/configuration/module#rule-resource): { [or](/configuration/module#condition): [ /* conditions */ ] } }, - { [resource](/configuration/module#rule-resource): [ /* conditions */ ] }, - // matches if any condition is matched (default for arrays) - { [resource](/configuration/module#rule-resource): { [not](/configuration/module#condition): /* condition */ } } - // matches if the condition is not matched - ], - <details><summary>/* Advanced module configuration (click to show) */</summary> - [noParse](/configuration/module#module-noparse): [ - /special-library\.js$/ - ], - // do not parse this module - unknownContextRequest: ".", - unknownContextRecursive: true, - unknownContextRegExp: /^\.\/.*$/, - unknownContextCritical: true, - exprContextRequest: ".", - exprContextRegExp: /^\.\/.*$/, - exprContextRecursive: true, - exprContextCritical: true, - wrappedContextRegExp: /.*/, - wrappedContextRecursive: true, - wrappedContextCritical: false, - // specifies default behavior for dynamic requests - </details> - }, - [resolve](/configuration/resolve): { - // options for resolving module requests - // (does not apply to resolving to loaders) - [modules](/configuration/resolve#resolve-modules): [ - "node_modules", - path.resolve(__dirname, "app") - ], - // directories where to look for modules - [extensions](/configuration/resolve#resolve-extensions): [".js", ".json", ".jsx", ".css"], - // extensions that are used - [alias](/configuration/resolve#resolve-alias): { - // a list of module name aliases - "module": "new-module", - // alias "module" -> "new-module" and "module/path/file" -> "new-module/path/file" - "only-module$": "new-module", - // alias "only-module" -> "new-module", but not "only-module/path/file" -> "new-module/path/file" - "module": path.resolve(__dirname, "app/third/module.js"), - // alias "module" -> "./app/third/module.js" and "module/file" results in error - // modules aliases are imported relative to the current context - }, - <details><summary>/* alternative alias syntax (click to show) */</summary> - [alias](/configuration/resolve#resolve-alias): [ - { - name: "module", - // the old request - alias: "new-module", - // the new request - onlyModule: true - // if true only "module" is aliased - // if false "module/inner/path" is also aliased - } - ], - </details> - <details><summary>/* Advanced resolve configuration (click to show) */</summary> - [symlinks](/configuration/resolve#resolve-symlinks): true, - // follow symlinks to new location - [descriptionFiles](/configuration/resolve#resolve-descriptionfiles): ["package.json"], - // files that are read for package description - [mainFields](/configuration/resolve#resolve-mainfields): ["main"], - // properties that are read from description file - // when a folder is requested - [aliasFields](/configuration/resolve#resolve-aliasfields): ["browser"], - // properties that are read from description file - // to alias requests in this package - [enforceExtension](/configuration/resolve#resolve-enforceextension): false, - // if true request must not include an extensions - // if false request may already include an extension - [moduleExtensions](/configuration/resolve#resolveloader-moduleextensions): ["-module"], - [enforceModuleExtension](/configuration/resolve#resolve-enforcemoduleextension): false, - // like extensions/enforceExtension but for module names instead of files - [unsafeCache](/configuration/resolve#resolve-unsafecache): true, - [unsafeCache](/configuration/resolve#resolve-unsafecache): {}, - // enables caching for resolved requests - // this is unsafe as folder structure may change - // but performance improvement is really big - [cachePredicate](/configuration/resolve#resolve-cachepredicate): (path, request) => true, - // predicate function which selects requests for caching - [plugins](/configuration/resolve#resolve-plugins): [ - // ... - ] - // additional plugins applied to the resolver - </details> - }, - [performance](/configuration/performance): { - <details><summary>[hints](/configuration/performance#performance-hints): "warning", // enum </summary> - [hints](/configuration/performance#performance-hints): "error", // emit errors for perf hints - [hints](/configuration/performance#performance-hints): false, // turn off perf hints - </details> - [maxAssetSize](/configuration/performance#performance-maxassetsize): 200000, // int (in bytes), - [maxEntrypointSize](/configuration/performance#performance-maxentrypointsize): 400000, // int (in bytes) - [assetFilter](/configuration/performance#performance-assetfilter): function(assetFilename) { - // Function predicate that provides asset filenames - return assetFilename.endsWith('.css') || assetFilename.endsWith('.js'); - } - }, - <details><summary>[devtool](/configuration/devtool): "source-map", // enum </summary> - [devtool](/configuration/devtool): "inline-source-map", // inlines SourceMap into original file - [devtool](/configuration/devtool): "eval-source-map", // inlines SourceMap per module - [devtool](/configuration/devtool): "hidden-source-map", // SourceMap without reference in original file - [devtool](/configuration/devtool): "cheap-source-map", // cheap-variant of SourceMap without module mappings - [devtool](/configuration/devtool): "cheap-module-source-map", // cheap-variant of SourceMap with module mappings - [devtool](/configuration/devtool): "eval", // no SourceMap, but named modules. Fastest at the expense of detail. - </details> - // enhance debugging by adding meta info for the browser devtools - // source-map most detailed at the expense of build speed. - [context](/configuration/entry-context#context): __dirname, // string (absolute path!) - // the home directory for webpack - // the [entry](/configuration/entry-context) and [module.rules.loader](/configuration/module#rule-loader) option - // is resolved relative to this directory - <details><summary>[target](/configuration/target): "web", // enum</summary> - [target](/configuration/target): "webworker", // WebWorker - [target](/configuration/target): "node", // Node.js via require - [target](/configuration/target): "async-node", // Node.js via fs and vm - [target](/configuration/target): "node-webkit", // nw.js - [target](/configuration/target): "electron-main", // electron, main process - [target](/configuration/target): "electron-renderer", // electron, renderer process - [target](/configuration/target): (compiler) => { /* ... */ }, // custom - </details> - // the environment in which the bundle should run - // changes chunk loading behavior and available modules - <details><summary>[externals](/configuration/externals): ["react", /^@angular\//],</summary> - [externals](/configuration/externals): "react", // string (exact match) - [externals](/configuration/externals): /^[a-z\-]+($|\/)/, // Regex - [externals](/configuration/externals): { // object - angular: "this angular", // this["angular"] - react: { // UMD - commonjs: "react", - commonjs2: "react", - amd: "react", - root: "React" - } - }, - [externals](/configuration/externals): (request) => { /* ... */ return "commonjs " + request } - </details> - // Don't follow/bundle these modules, but request them at runtime from the environment - [serve](https://github.com/webpack-contrib/webpack-serve#options): { //object - port: 1337, - content: './dist', - // ... - }, - // lets you provide options for webpack-serve - <details><summary>[stats](/configuration/stats): "errors-only",</summary> - [stats](/configuration/stats): { //object - assets: true, - colors: true, - errors: true, - errorDetails: true, - hash: true, - // ... - }, - </details> - // lets you precisely control what bundle information gets displayed - [devServer](/configuration/dev-server): { - proxy: { // proxy URLs to backend development server - '/api': 'http://localhost:3000' - }, - contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location - compress: true, // enable gzip compression - historyApiFallback: true, // true for index.html upon 404, object for multiple paths - hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin - https: false, // true for self-signed, object for cert authority - noInfo: true, // only errors & warns on hot reload - // ... - }, - [plugins](plugins): [ - // ... - ], - // list of additional plugins - <details><summary>/* Advanced configuration (click to show) */</summary> - [resolveLoader](/configuration/resolve#resolveloader): { /* same as resolve */ } - // separate resolve options for loaders - [parallelism](other-options#parallelism): 1, // number - // limit the number of parallel processed modules - [profile](other-options#profile): true, // boolean - // capture timing information - [bail](other-options#bail): true, //boolean - // fail out on the first error instead of tolerating it. - [cache](other-options#cache): false, // boolean - // disable/enable caching - [watch](watch#watch): true, // boolean - // enables watching - [watchOptions](watch#watchoptions): { - [aggregateTimeout](watch#watchoptions-aggregatetimeout): 1000, // in ms - // aggregates multiple changes to a single rebuild - [poll](watch#watchoptions-poll): true, - [poll](watch#watchoptions-poll): 500, // interval in ms - // enables polling mode for watching - // must be used on filesystems that doesn't notify on change - // i. e. nfs shares - }, - [node](node): { - // Polyfills and mocks to run Node.js- - // environment code in non-Node environments. - [console](node#node-console): false, // boolean | "mock" - [global](node#node-global): true, // boolean | "mock" - [process](node#node-process): true, // boolean - [__filename](node#node-__filename): "mock", // boolean | "mock" - [__dirname](node#node-__dirname): "mock", // boolean | "mock" - [Buffer](node#node-buffer): true, // boolean | "mock" - [setImmediate](node#node-setimmediate): true // boolean | "mock" | "empty" - }, - [recordsPath](other-options#recordspath): path.resolve(__dirname, "build/records.json"), - [recordsInputPath](other-options#recordsinputpath): path.resolve(__dirname, "build/records.json"), - [recordsOutputPath](other-options#recordsoutputpath): path.resolve(__dirname, "build/records.json"), - // TODO - </details> -} -``` - -## Use custom configuration file - -If for some reason you want to use custom configuration file depending on certain situations you can change this via command line by using the `--config` flag. - -__package.json__ - -```json -"scripts": { - "build": "webpack --config prod.config.js" -} -``` - -## Configuration file generators - -Want to rapidly generate webpack configuration file for your project requirements with few clicks away? - -[Generate Custom Webpack Configuration](https://generatewebpackconfig.netlify.com/) is an interactive portal you can play around by selecting custom webpack configuration options tailored for your frontend project. It automatically generates a minimal webpack configuration based on your selection of loaders/plugins, etc. - -[Visual tool for creating webpack configs](https://webpack.jakoblind.no/) is an online configuration tool for creating webpack configuration file where you can select any combination of features you need. It also generates a full example project based on your webpack configs. - - -# Configuration Languages - -webpack accepts configuration files written in multiple programming and data languages. The list of supported file extensions can be found at the [node-interpret](https://github.com/js-cli/js-interpret) package. Using [node-interpret](https://github.com/js-cli/js-interpret), webpack can handle many different types of configuration files. - - -## TypeScript - -To write the webpack configuration in [TypeScript](http://www.typescriptlang.org/), you would first install the necessary dependencies, i.e., TypeScript and the relevant type definitions from the [DefinitelyTyped](https://definitelytyped.org/) project: - -``` bash -npm install --save-dev typescript ts-node @types/node @types/webpack -# and, if using webpack-dev-server -npm install --save-dev @types/webpack-dev-server -``` - -and then proceed to write your configuration: - -__webpack.config.ts__ - -```typescript -import path from 'path'; -import webpack from 'webpack'; - -const config: webpack.Configuration = { - mode: 'production', - entry: './foo.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'foo.bundle.js' - } -}; - -export default config; -``` - -Above sample assumes version >= 2.7 or newer of TypeScript is used with the new `esModuleInterop` and `allowSyntheticDefaultImports` compiler options in your `tsconfig.json` file. - -Note that you'll also need to check your `tsconfig.json` file. If the module in `compilerOptions` in `tsconfig.json` is `commonjs`, the setting is complete, else webpack will fail with an error. This occurs because `ts-node` does not support any module syntax other than `commonjs`. - -There are two solutions to this issue: - -- Modify `tsconfig.json`. -- Install `tsconfig-paths`. - -The __first option__ is to open your `tsconfig.json` file and look for `compilerOptions`. Set `target` to `"ES5"` and `module` to `"CommonJS"` (or completely remove the `module` option). - -The __second option__ is to install the `tsconfig-paths` package: - -``` bash -npm install --save-dev tsconfig-paths -``` - -And create a separate TypeScript configuration specifically for your webpack configs: - -__tsconfig-for-webpack-config.json__ - -``` json -{ - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "esModuleInterop": true - } -} -``` - -T> `ts-node` can resolve a `tsconfig.json` file using the environment variable provided by `tsconfig-path`. - -Then set the environment variable `process.env.TS_NODE_PROJECT` provided by `tsconfig-path` like so: - -__package.json__ - -```json -{ - "scripts": { - "build": "TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack" - } -} -``` - - -## CoffeeScript - -Similarly, to use [CoffeeScript](http://coffeescript.org/), you would first install the necessary dependencies: - -``` bash -npm install --save-dev coffee-script -``` - -and then proceed to write your configuration: - -__webpack.config.coffee__ - -<!-- eslint-skip --> - -```js -HtmlWebpackPlugin = require('html-webpack-plugin') -webpack = require('webpack') -path = require('path') - -config = - mode: 'production' - entry: './path/to/my/entry/file.js' - output: - path: path.resolve(__dirname, 'dist') - filename: 'my-first-webpack.bundle.js' - module: rules: [ { - test: /\.(js|jsx)$/ - use: 'babel-loader' - } ] - plugins: [ - new HtmlWebpackPlugin(template: './src/index.html') - ] - -module.exports = config -``` - - -## Babel and JSX - -In the example below JSX (React JavaScript Markup) and Babel are used to create a JSON Configuration that webpack can understand. - -> Courtesy of [Jason Miller](https://twitter.com/_developit/status/769583291666169862) - -First install the necessary dependencies: - -``` bash -npm install --save-dev babel-register jsxobj babel-preset-es2015 -``` - -__.babelrc__ - -``` json -{ - "presets": [ "es2015" ] -} -``` - -__webpack.config.babel.js__ - -``` js -import jsxobj from 'jsxobj'; - -// example of an imported plugin -const CustomPlugin = config => ({ - ...config, - name: 'custom-plugin' -}); - -export default ( - <webpack target="web" watch mode="production"> - <entry path="src/index.js" /> - <resolve> - <alias {...{ - react: 'preact-compat', - 'react-dom': 'preact-compat' - }} /> - </resolve> - <plugins> - <CustomPlugin foo="bar" /> - </plugins> - </webpack> -); -``` - -W> If you are using Babel elsewhere and have `modules` set to `false`, you will have to either maintain two separate `.babelrc` files or use `const jsxobj = require('jsxobj');` and `module.exports` instead of the new `import` and `export` syntax. This is because while Node does support many new ES6 features, they don't yet support ES6 module syntax. - - -# Configuration Types - -Besides exporting a single config object, there are a few more ways that cover other needs as well. - - -## Exporting a Function - -Eventually you will find the need to disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production). You have (at least) two options: - -One option is to export a function from your webpack config instead of exporting an object. The function will be invoked with two arguments: - -- An environment as the first parameter. See the [environment options CLI documentation](/api/cli#environment-options) for syntax examples. -- An options map (`argv`) as the second parameter. This describes the options passed to webpack, with keys such as [`output-filename`](/api/cli/#output-options) and [`optimize-minimize`](/api/cli/#optimize-options). - -```diff --module.exports = { -+module.exports = function(env, argv) { -+ return { -+ mode: env.production ? 'production' : 'development', -+ devtool: env.production ? 'source-maps' : 'eval', - plugins: [ - new TerserPlugin({ - terserOptions: { -+ compress: argv['optimize-minimize'] // only if -p or --optimize-minimize were passed - } - }) - ] -+ }; -}; -``` - - -## Exporting a Promise - -webpack will run the function exported by the configuration file and wait for a Promise to be returned. Handy when you need to asynchronously load configuration variables. - -```js -module.exports = () => { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve({ - entry: './app.js', - /* ... */ - }); - }, 5000); - }); -}; -``` - - -## Exporting multiple configurations - -Instead of exporting a single configuration object/function, you may export multiple configurations (multiple functions are supported since webpack 3.1.0). When running webpack, all configurations are built. For instance, this is useful for [bundling a library](/guides/author-libraries) for multiple [targets](/configuration/output#output-librarytarget) such as AMD and CommonJS: - -```js -module.exports = [{ - output: { - filename: './dist-amd.js', - libraryTarget: 'amd' - }, - name: 'amd', - entry: './app.js', - mode: 'production', -}, { - output: { - filename: './dist-commonjs.js', - libraryTarget: 'commonjs' - }, - name: 'commonjs', - entry: './app.js', - mode: 'production', -}]; -``` - -T> If you pass a name to [`--config-name`](/api/cli/#config-options) flag, webpack will only build that specific configuration. - - -# Entry and Context - -The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. - - -## `context` - -`string` - -The base directory, an __absolute path__, for resolving entry points and loaders from configuration. - -``` js -module.exports = { - //... - context: path.resolve(__dirname, 'app') -}; -``` - -By default the current directory is used, but it's recommended to pass a value in your configuration. This makes your configuration independent from CWD (current working directory). - ---- - - -## `entry` - -`string | [string] | object { <key>: string | [string] } | (function: () => string | [string] | object { <key>: string | [string] })` - -The point or points to enter the application. At this point the application starts executing. If an array is passed all items will be executed. - -A dynamically loaded module is __not__ an entry point. - -Simple rule: one entry point per HTML page. SPA: one entry point, MPA: multiple entry points. - -```js -module.exports = { - //... - entry: { - home: './home.js', - about: './about.js', - contact: './contact.js' - } -}; -``` - - -### Naming - -If a string or array of strings is passed, the chunk is named `main`. If an object is passed, each key is the name of a chunk, and the value describes the entry point for the chunk. - - -### Dynamic entry - -If a function is passed then it will be invoked on every [make](/api/compiler-hooks/#make) event. - -> Note that the make event triggers when webpack starts and for every invalidation when [watching for file changes](/configuration/watch/). - -```js -module.exports = { - //... - entry: () => './demo' -}; -``` - -or - -```js -module.exports = { - //... - entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])) -}; -``` - -For example: you can use dynamic entries to get the actual entries from an external source (remote server, file system content or database): - -__webpack.config.js__ - -``` js -module.exports = { - entry() { - return fetchPathsFromSomeExternalSource(); // returns a promise that will be resolved with something like ['src/main-layout.js', 'src/admin-layout.js'] - } -}; -``` - -When combining with the [`output.library`](/configuration/output#output-library) option: If an array is passed only the last item is exported. - - -# Output - -The top-level `output` key contains set of options instructing webpack on how and where it should output your bundles, assets and anything else you bundle or load with webpack. - - -## `output.auxiliaryComment` - -`string` `object` - -When used in tandem with [`output.library`](#output-library) and [`output.libraryTarget`](#output-librarytarget), this option allows users to insert comments within the export wrapper. To insert the same comment for each `libraryTarget` type, set `auxiliaryComment` to a string: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - library: 'someLibName', - libraryTarget: 'umd', - filename: 'someLibName.js', - auxiliaryComment: 'Test Comment' - } -}; -``` - -which will yield the following: - -__webpack.config.js__ - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - // Test Comment - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require('lodash')); - // Test Comment - else if(typeof define === 'function' && define.amd) - define(['lodash'], factory); - // Test Comment - else if(typeof exports === 'object') - exports['someLibName'] = factory(require('lodash')); - // Test Comment - else - root['someLibName'] = factory(root['_']); -})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { - // ... -}); -``` - -For fine-grained control over each `libraryTarget` comment, pass an object: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - //... - auxiliaryComment: { - root: 'Root Comment', - commonjs: 'CommonJS Comment', - commonjs2: 'CommonJS2 Comment', - amd: 'AMD Comment' - } - } -}; -``` - - -## `output.chunkFilename` - -`string` - -This option determines the name of non-entry chunk files. See [`output.filename`](#output-filename) option for details on the possible values. - -Note that these filenames need to be generated at runtime to send the requests for chunks. Because of this, placeholders like `[name]` and `[chunkhash]` need to add a mapping from chunk id to placeholder value to the output bundle with the webpack runtime. This increases the size and may invalidate the bundle when placeholder value for any chunk changes. - -By default `[id].js` is used or a value inferred from [`output.filename`](#output-filename) (`[name]` is replaced with `[id]` or `[id].` is prepended). - - -## `output.chunkLoadTimeout` - -`integer` - -Number of milliseconds before chunk request expires, defaults to 120 000. This option is supported since webpack 2.6.0. - - -## `output.crossOriginLoading` - -`boolean` `string` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks, by adding script tags. - -Enable [cross-origin](https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-crossorigin) loading of chunks. The following values are accepted... - -`crossOriginLoading: false` - Disable cross-origin loading (default) - -`crossOriginLoading: 'anonymous'` - Enable cross-origin loading __without credentials__ - -`crossOriginLoading: 'use-credentials'` - Enable cross-origin loading __with credentials__ - - -## `output.jsonpScriptType` - -`string` - -Allows customization of the `script` type webpack injects `script` tags into the DOM to download async chunks. The following options are available: - -- `'text/javascript'` (default) -- `'module'`: Use with ES6 ready code. - - -## `output.devtoolFallbackModuleFilenameTemplate` - -`string | function(info)` - -A fallback used when the template string or function above yields duplicates. - -See [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). - - -## `output.devtoolLineToLine` - -`boolean | object` - -> Avoid using this option as it is __deprecated__ and will soon be removed. - -Enables line to line mapping for all or some modules. This produces a simple source map where each line of the generated source is mapped to the same line of the original source. This is a performance optimization and should only be used if all input lines match generated lines. - -Pass a boolean to enable or disable this feature for all modules (defaults to `false`). An object with `test`, `include`, `exclude` is also allowed. For example, to enable this feature for all javascript files within a certain directory: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - devtoolLineToLine: { test: /\.js$/, include: 'src/utilities' } - } -}; -``` - - -## `output.devtoolModuleFilenameTemplate` - -`string | function(info)` - -This option is only used when [`devtool`](/configuration/devtool) uses an options which requires module names. - -Customize the names used in each source map's `sources` array. This can be done by passing a template string or function. For example, when using `devtool: 'eval'`, this is the default: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - devtoolModuleFilenameTemplate: 'webpack://[namespace]/[resource-path]?[loaders]' - } -}; -``` - -The following substitutions are available in template strings (via webpack's internal [`ModuleFilenameHelpers`](https://github.com/webpack/webpack/blob/master/lib/ModuleFilenameHelpers.js)): - -| Template | Description | -| ------------------------ | ----------- | -| [absolute-resource-path] | The absolute filename | -| [all-loaders] | Automatic and explicit loaders and params up to the name of the first loader | -| [hash] | The hash of the module identifier | -| [id] | The module identifier | -| [loaders] | Explicit loaders and params up to the name of the first loader | -| [resource] | The path used to resolve the file and any query params used on the first loader | -| [resource-path] | The path used to resolve the file without any query params | -| [namespace] | The modules namespace. This is usually the library name when building as a library, empty otherwise | - -When using a function, the same options are available camel-cased via the `info` parameter: - -```javascript -module.exports = { - //... - output: { - devtoolModuleFilenameTemplate: info => { - return `webpack:///${info.resourcePath}?${info.loaders}`; - } - } -}; -``` - -If multiple modules would result in the same name, [`output.devtoolFallbackModuleFilenameTemplate`](#output-devtoolfallbackmodulefilenametemplate) is used instead for these modules. - - -## `output.devtoolNamespace` - -`string` - -This option determines the modules namespace used with the [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). When not specified, it will default to the value of: [`output.library`](#output-library). It's used to prevent source file path collisions in source maps when loading multiple libraries built with webpack. - -For example, if you have 2 libraries, with namespaces `library1` and `library2`, which both have a file `./src/index.js` (with potentially different contents), they will expose these files as `webpack://library1/./src/index.js` and `webpack://library2/./src/index.js`. - - -## `output.filename` - -`string` `function` - -This option determines the name of each output bundle. The bundle is written to the directory specified by the [`output.path`](#output-path) option. - -For a single [`entry`](/configuration/entry-context#entry) point, this can be a static name. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: 'bundle.js' - } -}; -``` - -However, when creating multiple bundles via more than one entry point, code splitting, or various plugins, you should use one of the following substitutions to give each bundle a unique name... - -Using entry name: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[name].bundle.js' - } -}; -``` - -Using internal chunk id: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[id].bundle.js' - } -}; -``` - -Using the unique hash generated for every build: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[name].[hash].bundle.js' - } -}; -``` - -Using hashes based on each chunks' content: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[chunkhash].bundle.js' - } -}; -``` - -Using hashes generated for extracted content: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[contenthash].bundle.css' - } -}; -``` - -Using function to return the filename: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: (chunkData) => { - return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js'; - }, - } -}; -``` - -Make sure to read the [Caching guide](/guides/caching) for details. There are more steps involved than just setting this option. - -Note this option is called filename but you are still allowed to use something like `'js/[name]/bundle.js'` to create a folder structure. - -Note this option does not affect output files for on-demand-loaded chunks. For these files the [`output.chunkFilename`](#output-chunkfilename) option is used. Files created by loaders also aren't affected. In this case you would have to try the specific loader's available options. - -The following substitutions are available in template strings (via webpack's internal [`TemplatedPathPlugin`](https://github.com/webpack/webpack/blob/master/lib/TemplatedPathPlugin.js)): - -| Template | Description | -| ----------- | ----------------------------------------------------------------------------------- | -| [hash] | The hash of the module identifier | -| [chunkhash] | The hash of the chunk content | -| [name] | The module name | -| [id] | The module identifier | -| [query] | The module query, i.e., the string following `?` in the filename | -| [function] | The function, which can return filename [string] | - -The lengths of `[hash]` and `[chunkhash]` can be specified using `[hash:16]` (defaults to 20). Alternatively, specify [`output.hashDigestLength`](#output-hashdigestlength) to configure the length globally. - -If using a function for this option, the function will be passed an object containing the substitutions in the table above. - -T> When using the [`ExtractTextWebpackPlugin`](/plugins/extract-text-webpack-plugin), use `[contenthash]` to obtain a hash of the extracted file (neither `[hash]` nor `[chunkhash]` work). - - -## `output.hashDigest` - -The encoding to use when generating the hash, defaults to `'hex'`. All encodings from Node.JS' [`hash.digest`](https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding) are supported. Using `'base64'` for filenames might be problematic since it has the character `/` in its alphabet. Likewise `'latin1'` could contain any character. - - -## `output.hashDigestLength` - -The prefix length of the hash digest to use, defaults to `20`. - - -## `output.hashFunction` - -`string|function` - -The hashing algorithm to use, defaults to `'md4'`. All functions from Node.JS' [`crypto.createHash`](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options) are supported. Since `4.0.0-alpha2`, the `hashFunction` can now be a constructor to a custom hash function. You can provide a non-crypto hash function for performance reasons. - -```javascript -module.exports = { - //... - output: { - hashFunction: require('metrohash').MetroHash64 - } -}; -``` - -Make sure that the hashing function will have `update` and `digest` methods available. - -## `output.hashSalt` - -An optional salt to update the hash via Node.JS' [`hash.update`](https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding). - - -## `output.hotUpdateChunkFilename` - -`string` `function` - -Customize the filenames of hot update chunks. See [`output.filename`](#output-filename) option for details on the possible values. - -The only placeholders allowed here are `[id]` and `[hash]`, the default being: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - hotUpdateChunkFilename: '[id].[hash].hot-update.js' - } -}; -``` - -Here is no need to change it. - - -## `output.hotUpdateFunction` - -`function` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading hot updates. - -A JSONP function used to asynchronously load hot-update chunks. - -For details see [`output.jsonpFunction`](#output-jsonpfunction). - - -## `output.hotUpdateMainFilename` - -`string` `function` - -Customize the main hot update filename. See [`output.filename`](#output-filename) option for details on the possible values. - -`[hash]` is the only available placeholder, the default being: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - hotUpdateMainFilename: '[hash].hot-update.json' - } -}; -``` - -Here is no need to change it. - - -## `output.jsonpFunction` - -`string` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks. - -A JSONP function name used to asynchronously load chunks or join multiple initial chunks (SplitChunksPlugin, AggressiveSplittingPlugin). - -This needs to be changed if multiple webpack runtimes (from different compilation) are used on the same webpage. - -If using the [`output.library`](#output-library) option, the library name is automatically appended. - - -## `output.library` - -`string` or `object` (since webpack 3.1.0; for `libraryTarget: 'umd'`) - -How the value of the `output.library` is used depends on the value of the [`output.libraryTarget`](#output-librarytarget) option; please refer to that section for the complete details. Note that the default option for `output.libraryTarget` is `var`, so if the following configuration option is used: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary' - } -}; -``` - -The variable `MyLibrary` will be bound with the return value of your entry file, if the resulting output is included as a script tag in an HTML page. - -W> Note that if an `array` is provided as an `entry` point, only the last module in the array will be exposed. If an `object` is provided, it can be exposed using an `array` syntax (see [this example](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) for details). - -T> Read the [authoring libraries guide](/guides/author-libraries) guide for more information on `output.library` as well as `output.libraryTarget`. - - -## `output.libraryExport` - -`string | string[]` - -Configure which module or modules will be exposed via the `libraryTarget`. It is `undefined` by default, same behaviour will be applied if you set `libraryTarget` to an empty string e.g. `''` it will export the whole (namespace) object. The examples below demonstrate the effect of this config when using `libraryTarget: 'var'`. - -The following configurations are supported: - -`libraryExport: 'default'` - The __default export of your entry point__ will be assigned to the library target: - -```javascript -// if your entry has a default export of `MyDefaultModule` -var MyDefaultModule = _entry_return_.default; -``` - -`libraryExport: 'MyModule'` - The __specified module__ will be assigned to the library target: - -```javascript -var MyModule = _entry_return_.MyModule; -``` - -`libraryExport: ['MyModule', 'MySubModule']` - The array is interpreted as a __path to a module__ to be assigned to the library target: - -```javascript -var MySubModule = _entry_return_.MyModule.MySubModule; -``` - -With the `libraryExport` configurations specified above, the resulting libraries could be utilized as such: - -```javascript -MyDefaultModule.doSomething(); -MyModule.doSomething(); -MySubModule.doSomething(); -``` - - -## `output.libraryTarget` - -`string: 'var'` - -Configure how the library will be exposed. Any one of the following options can be used. Please note that this option works in conjunction with the value assigned to [`output.library`](#output-library). For the following examples, it is assumed that this value is configured as `MyLibrary`. - -T> Note that `_entry_return_` in the example code below is the value returned by the entry point. In the bundle itself, it is the output of the function that is generated by webpack from the entry point. - -### Expose a Variable - -These options assign the return value of the entry point (e.g. whatever the entry point exported) to the name provided by `output.library` at whatever scope the bundle was included at. - -`libraryTarget: 'var'` - (default) When your library is loaded, the __return value of your entry point__ will be assigned to a variable: - -```javascript -var MyLibrary = _entry_return_; - -// In a separate script... -MyLibrary.doSomething(); -``` - -W> When using this option, an empty `output.library` will result in no assignment. - - -`libraryTarget: 'assign'` - This will generate an implied global which has the potential to reassign an existing value (use with caution). - -```javascript -MyLibrary = _entry_return_; -``` - -Be aware that if `MyLibrary` isn't defined earlier your library will be set in global scope. - -W> When using this option, an empty `output.library` will result in a broken output bundle. - - -### Expose Via Object Assignment - -These options assign the return value of the entry point (e.g. whatever the entry point exported) to a specific object under the name defined by `output.library`. - -If `output.library` is not assigned a non-empty string, the default behavior is that all properties returned by the entry point will be assigned to the object as defined for the particular `output.libraryTarget`, via the following code fragment: - -```javascript -(function(e, a) { for(var i in a) { e[i] = a[i]; } }(output.libraryTarget, _entry_return_)); -``` - -W> Note that not setting a `output.library` will cause all properties returned by the entry point to be assigned to the given object; there are no checks against existing property names. - -`libraryTarget: "this"` - The __return value of your entry point__ will be assigned to this under the property named by `output.library`. The meaning of `this` is up to you: - -```javascript -this['MyLibrary'] = _entry_return_; - -// In a separate script... -this.MyLibrary.doSomething(); -MyLibrary.doSomething(); // if this is window -``` - -`libraryTarget: 'window'` - The __return value of your entry point__ will be assigned to the `window` object using the `output.library` value. - -```javascript -window['MyLibrary'] = _entry_return_; - -window.MyLibrary.doSomething(); -``` - - -`libraryTarget: 'global'` - The __return value of your entry point__ will be assigned to the `global` object using the `output.library` value. - -```javascript -global['MyLibrary'] = _entry_return_; - -global.MyLibrary.doSomething(); -``` - - -`libraryTarget: 'commonjs'` - The __return value of your entry point__ will be assigned to the `exports` object using the `output.library` value. As the name implies, this is used in CommonJS environments. - -```javascript -exports['MyLibrary'] = _entry_return_; - -require('MyLibrary').doSomething(); -``` - -### Module Definition Systems - -These options will result in a bundle that comes with a more complete header to ensure compatibility with various module systems. The `output.library` option will take on a different meaning under the following `output.libraryTarget` options. - - -`libraryTarget: 'commonjs2'` - The __return value of your entry point__ will be assigned to the `module.exports`. As the name implies, this is used in CommonJS environments: - -```javascript -module.exports = _entry_return_; - -require('MyLibrary').doSomething(); -``` - -Note that `output.library` is omitted, thus it is not required for this particular `output.libraryTarget`. - -T> Wondering the difference between CommonJS and CommonJS2 is? While they are similar, there are some subtle differences between them that are not usually relevant in the context of webpack. (For further details, please [read this issue](https://github.com/webpack/webpack/issues/1114).) - - -`libraryTarget: 'amd'` - This will expose your library as an AMD module. - -AMD modules require that the entry chunk (e.g. the first script loaded by the `<script>` tag) be defined with specific properties, such as `define` and `require` which is typically provided by RequireJS or any compatible loaders (such as almond). Otherwise, loading the resulting AMD bundle directly will result in an error like `define is not defined`. - -So, with the following configuration... - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary', - libraryTarget: 'amd' - } -}; -``` - -The generated output will be defined with the name "MyLibrary", i.e. - -```javascript -define('MyLibrary', [], function() { - return _entry_return_; -}); -``` - -The bundle can be included as part of a script tag, and the bundle can be invoked like so: - -```javascript -require(['MyLibrary'], function(MyLibrary) { - // Do something with the library... -}); -``` - -If `output.library` is undefined, the following is generated instead. - -```javascript -define([], function() { - return _entry_return_; -}); -``` - -This bundle will not work as expected, or not work at all (in the case of the almond loader) if loaded directly with a `<script>` tag. It will only work through a RequireJS compatible asynchronous module loader through the actual path to that file, so in this case, the `output.path` and `output.filename` may become important for this particular setup if these are exposed directly on the server. - - -`libraryTarget: 'amd-require'` - This packages your output with an immediately-executed AMD `require(dependencies, factory)` wrapper. - -The `'amd-require'` target allows for the use of AMD dependencies without needing a separate later invocation. As with the `'amd'` target, this depends on the appropriate [`require` function](https://github.com/amdjs/amdjs-api/blob/master/require.md) being available in the environment in which the webpack output is loaded. - -With this target, the library name is ignored. - - -`libraryTarget: 'umd'` - This exposes your library under all the module definitions, allowing it to work with CommonJS, AMD and as global variable. Take a look at the [UMD Repository](https://github.com/umdjs/umd) to learn more. - -In this case, you need the `library` property to name your module: - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary', - libraryTarget: 'umd' - } -}; -``` - -And finally the output is: - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports['MyLibrary'] = factory(); - else - root['MyLibrary'] = factory(); -})(typeof self !== 'undefined' ? self : this, function() { - return _entry_return_; -}); -``` - -Note that omitting `library` will result in the assignment of all properties returned by the entry point be assigned directly to the root object, as documented under the [object assignment section](#expose-via-object-assignment). Example: - -```javascript -module.exports = { - //... - output: { - libraryTarget: 'umd' - } -}; -``` - -The output will be: - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else { - var a = factory(); - for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; - } -})(typeof self !== 'undefined' ? self : this, function() { - return _entry_return_; -}); -``` - -Since webpack 3.1.0, you may specify an object for `library` for differing names per targets: - -```javascript -module.exports = { - //... - output: { - library: { - root: 'MyLibrary', - amd: 'my-library', - commonjs: 'my-common-library' - }, - libraryTarget: 'umd' - } -}; -``` - -Module proof library. - - -### Other Targets - -`libraryTarget: 'jsonp'` - This will wrap the return value of your entry point into a jsonp wrapper. - -``` javascript -MyLibrary(_entry_return_); -``` - -The dependencies for your library will be defined by the [`externals`](/configuration/externals/) config. - - -## `output.path` - -`string` - -The output directory as an __absolute__ path. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - path: path.resolve(__dirname, 'dist/assets') - } -}; -``` - -Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. - - -## `output.pathinfo` - -`boolean` - -Tells webpack to include comments in bundles with information about the contained modules. This option defaults to `true` in `development` and `false` in `production` [mode](/concepts/mode/) respectively. - -W> While the data this comments can provide is very useful during development when reading the generated code, it __should not__ be used in production. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - pathinfo: true - } -}; -``` - -Note it also adds some info about tree shaking to the generated bundle. - - -## `output.publicPath` - -`string: ''` `function` - -This is an important option when using on-demand-loading or loading external resources like images, files, etc. If an incorrect value is specified you'll receive 404 errors while loading these resources. - -This option specifies the __public URL__ of the output directory when referenced in a browser. A relative URL is resolved relative to the HTML page (or `<base>` tag). Server-relative URLs, protocol-relative URLs or absolute URLs are also possible and sometimes required, i. e. when hosting assets on a CDN. - -The value of the option is prefixed to every URL created by the runtime or loaders. Because of this __the value of this option ends with `/`__ in most cases. - -Simple rule: The URL of your [`output.path`](#output-path) from the view of the HTML page. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - path: path.resolve(__dirname, 'public/assets'), - publicPath: 'https://cdn.example.com/assets/' - } -}; -``` - -For this configuration: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - publicPath: '/assets/', - chunkFilename: '[id].chunk.js' - } -}; -``` - -A request to a chunk will look like `/assets/4.chunk.js`. - -A loader outputting HTML might emit something like this: - -```html -<link href="/assets/spinner.gif" /> -``` - -or when loading an image in CSS: - -```css -background-image: url(/assets/spinner.gif); -``` - -The webpack-dev-server also takes a hint from `publicPath`, using it to determine where to serve the output files from. - -Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. - -Examples: - -```javascript -module.exports = { - //... - output: { - // One of the below - publicPath: 'https://cdn.example.com/assets/', // CDN (always HTTPS) - publicPath: '//cdn.example.com/assets/', // CDN (same protocol) - publicPath: '/assets/', // server-relative - publicPath: 'assets/', // relative to HTML page - publicPath: '../assets/', // relative to HTML page - publicPath: '', // relative to HTML page (same directory) - } -}; -``` - -In cases where the `publicPath` of output files can't be known at compile time, it can be left blank and set dynamically at runtime in the entry file using the [free variable](https://stackoverflow.com/questions/12934929/what-are-free-variables) `__webpack_public_path__`. - -```javascript -__webpack_public_path__ = myRuntimePublicPath; - -// rest of your application entry -``` - -See [this discussion](https://github.com/webpack/webpack/issues/2776#issuecomment-233208623) for more information on `__webpack_public_path__`. - - -## `output.sourceMapFilename` - -`string` - -This option is only used when [`devtool`](/configuration/devtool) uses a SourceMap option which writes an output file. - -Configure how source maps are named. By default `'[file].map'` is used. - -The `[name]`, `[id]`, `[hash]` and `[chunkhash]` substitutions from [#output-filename](#output-filename) can be used. In addition to those, you can use substitutions listed below. The `[file]` placeholder is replaced with the filename of the original file. We recommend __only using the `[file]` placeholder__, as the other placeholders won't work when generating SourceMaps for non-chunk files. - -| Template | Description | -| -------------------------- | ----------------------------------------------------------------------------------- | -| [file] | The module filename | -| [filebase] | The module [basename](https://nodejs.org/api/path.html#path_path_basename_path_ext) | - - -## `output.sourcePrefix` - -`string` - -Change the prefix for each line in the output bundles. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - sourcePrefix: '\t' - } -}; -``` - -Note by default an empty string is used. Using some kind of indentation makes bundles look more pretty, but will cause issues with multi-line strings. - -There is no need to change it. - - -## `output.strictModuleExceptionHandling` - -`boolean` - -Tell webpack to remove a module from the module instance cache (`require.cache`) if it throws an exception when it is `require`d. - -It defaults to `false` for performance reasons. - -When set to `false`, the module is not removed from cache, which results in the exception getting thrown only on the first `require` call (making it incompatible with node.js). - -For instance, consider `module.js`: - -```javascript -throw new Error('error'); -``` - -With `strictModuleExceptionHandling` set to `false`, only the first `require` throws an exception: - -```javascript -// with strictModuleExceptionHandling = false -require('module'); // <- throws -require('module'); // <- doesn't throw -``` - -Instead, with `strictModuleExceptionHandling` set to `true`, all `require`s of this module throw an exception: - -```javascript -// with strictModuleExceptionHandling = true -require('module'); // <- throws -require('module'); // <- also throws -``` - - -## `output.umdNamedDefine` - -`boolean` - -When using `libraryTarget: "umd"`, setting: - -```javascript -module.exports = { - //... - output: { - umdNamedDefine: true - } -}; -``` - -will name the AMD module of the UMD build. Otherwise an anonymous `define` is used. - - -# Module - -These options determine how the [different types of modules](/concepts/modules) within a project will be treated. - - -## `module.noParse` - -`RegExp | [RegExp] | function | string | [string]` - -Prevent webpack from parsing any files matching the given regular expression(s). Ignored files __should not__ have calls to `import`, `require`, `define` or any other importing mechanism. This can boost build performance when ignoring large libraries. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - noParse: /jquery|lodash/, - } -}; -``` - -```javascript -module.exports = { - //... - module: { - noParse: (content) => /jquery|lodash/.test(content) - } -}; -``` - - -## `module.rules` - -`[Rule]` - -An array of [Rules](#rule) which are matched to requests when modules are created. These rules can modify how the module is created. They can apply loaders to the module, or modify the parser. - - -## Rule - -`object` - -A Rule can be separated into three parts — Conditions, Results and nested Rules. - - -### Rule Conditions - -There are two input values for the conditions: - -1. The resource: An absolute path to the file requested. It's already resolved according to the [`resolve` rules](/configuration/resolve). - -2. The issuer: An absolute path to the file of the module which requested the resource. It's the location of the import. - -__Example:__ When we `import './style.css'` within `app.js`, the resource is `/path/to/style.css` and the issuer is `/path/to/app.js`. - -In a Rule the properties [`test`](#rule-test), [`include`](#rule-include), [`exclude`](#rule-exclude) and [`resource`](#rule-resource) are matched with the resource and the property [`issuer`](#rule-issuer) is matched with the issuer. - -When using multiple conditions, all conditions must match. - -W> Be careful! The resource is the _resolved_ path of the file, which means symlinked resources are the real path _not_ the symlink location. This is good to remember when using tools that symlink packages (like `npm link`), common conditions like `/node_modules/` may inadvertently miss symlinked files. Note that you can turn off symlink resolving (so that resources are resolved to the symlink path) via [`resolve.symlinks`](/configuration/resolve#resolve-symlinks). - - -### Rule results - -Rule results are used only when the Rule condition matches. - -There are two output values of a Rule: - -1. Applied loaders: An array of loaders applied to the resource. -2. Parser options: An options object which should be used to create the parser for this module. - -These properties affect the loaders: [`loader`](#rule-loader), [`options`](#rule-options-rule-query), [`use`](#rule-use). - -For compatibility also these properties: [`query`](#rule-options-rule-query), [`loaders`](#rule-loaders). - -The [`enforce`](#rule-enforce) property affects the loader category. Whether it's a normal, pre- or post- loader. - -The [`parser`](#rule-parser) property affects the parser options. - - -## Nested rules - -Nested rules can be specified under the properties [`rules`](#rule-rules) and [`oneOf`](#rule-oneof). - -These rules are evaluated when the Rule condition matches. - - -## `Rule.enforce` - -`string` - -Possible values: `'pre' | 'post'` - -Specifies the category of the loader. No value means normal loader. - -There is also an additional category "inlined loader" which are loaders applied inline of the import/require. - -There are two phases that all loaders enter one after the other: - -1. __Pitching__ phase: the pitch method on loaders is called in the order `post, inline, normal, pre`. See [Pitching Loader](/api/loaders/#pitching-loader) for details. -2. __Normal__ phase: the normal method on loaders is executed in the order `pre, normal, inline, post`. Transformation on the source code of a module happens in this phase. - -All normal loaders can be omitted (overridden) by prefixing `!` in the request. - -All normal and pre loaders can be omitted (overridden) by prefixing `-!` in the request. - -All normal, post and pre loaders can be omitted (overridden) by prefixing `!!` in the request. - -Inline loaders and `!` prefixes should not be used as they are non-standard. They may be use by loader generated code. - - -## `Rule.exclude` - -`Rule.exclude` is a shortcut to `Rule.resource.exclude`. If you supply a `Rule.exclude` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.exclude`](#condition) for details. - - -## `Rule.include` - -`Rule.include` is a shortcut to `Rule.resource.include`. If you supply a `Rule.include` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.include`](#condition) for details. - - -## `Rule.issuer` - -A [`Condition`](#condition) to match against the module that issued the request. In the following example, the `issuer` for the `a.js` request would be the path to the `index.js` file. - -__index.js__ - -```javascript -import A from './a.js'; -``` - -This option can be used to apply loaders to the dependencies of a specific module or set of modules. - - -## `Rule.loader` - -`Rule.loader` is a shortcut to `Rule.use: [ { loader } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.loader`](#useentry) for details. - - -## `Rule.loaders` - -W> This option is __deprecated__ in favor of `Rule.use`. - -`Rule.loaders` is an alias to `Rule.use`. See [`Rule.use`](#rule-use) for details. - - -## `Rule.oneOf` - -An array of [`Rules`](#rule) from which only the first matching Rule is used when the Rule matches. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - oneOf: [ - { - resourceQuery: /inline/, // foo.css?inline - use: 'url-loader' - }, - { - resourceQuery: /external/, // foo.css?external - use: 'file-loader' - } - ] - } - ] - } -}; -``` - -## `Rule.options` / `Rule.query` - -`Rule.options` and `Rule.query` are shortcuts to `Rule.use: [ { options } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.options`](#useentry) for details. - -W> `Rule.query` is deprecated in favor of `Rule.options` and `UseEntry.options`. - - -## `Rule.parser` - -An object with parser options. All applied parser options are merged. - -Parsers may inspect these options and disable or reconfigure themselves accordingly. Most of the default plugins interpret the values as follows: - -- Setting the option to `false` disables the parser. -- Setting the option to `true` or leaving it `undefined` enables the parser. - -However, parser plugins may accept more than just a boolean. For example, the internal `NodeStuffPlugin` can accept an object instead of `true` to add additional options for a particular Rule. - -__Examples__ (parser options by the default plugins): - -```js-with-links -module.exports = { - //... - module: { - rules: [ - { - //... - parser: { - amd: false, // disable AMD - commonjs: false, // disable CommonJS - system: false, // disable SystemJS - harmony: false, // disable ES2015 Harmony import/export - requireInclude: false, // disable require.include - requireEnsure: false, // disable require.ensure - requireContext: false, // disable require.context - browserify: false, // disable special handling of Browserify bundles - requireJs: false, // disable requirejs.* - node: false, // disable __dirname, __filename, module, require.extensions, require.main, etc. - node: {...} // reconfigure [node](/configuration/node) layer on module level - } - } - ] - } -} -``` - - -## `Rule.resource` - -A [`Condition`](#condition) matched with the resource. You can either supply a `Rule.resource` option or use the shortcut options `Rule.test`, `Rule.exclude`, and `Rule.include`. See details in [`Rule` conditions](#rule-conditions). - - -## `Rule.resourceQuery` - -A [`Condition`](#condition) matched with the resource query. This option is used to test against the query section of a request string (i.e. from the question mark onwards). If you were to `import Foo from './foo.css?inline'`, the following condition would match: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - resourceQuery: /inline/, - use: 'url-loader' - } - ] - } -}; -``` - - -## `Rule.rules` - -An array of [`Rules`](#rule) that is also used when the Rule matches. - - -## `Rule.sideEffects` - -`bool` - -Indicate what parts of the module contain side effects. See [Tree Shaking](/guides/tree-shaking/#mark-the-file-as-side-effect-free) for details. - - -## `Rule.test` - -`Rule.test` is a shortcut to `Rule.resource.test`. If you supply a `Rule.test` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.test`](#condition) for details. - - -## `Rule.type` - -`string` - -Possible values: `'javascript/auto' | 'javascript/dynamic' | 'javascript/esm' | 'json' | 'webassembly/experimental'` - -`Rule.type` sets the type for a matching module. This prevents defaultRules and their default importing behaviors from occurring. For example, if you want to load a `.json` file through a custom loader, you'd need to set the `type` to `javascript/auto` to bypass webpack's built-in json importing. (See [v4.0 changelog](https://github.com/webpack/webpack/releases/tag/v4.0.0) for more details) - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - //... - { - test: /\.json$/, - type: 'javascript/auto', - loader: 'custom-json-loader' - } - ] - } -}; -``` - - -## `Rule.use` - -A list of [UseEntries](#useentry) which are applied to modules. Each entry specifies a loader to be used. - -Passing a string (i.e. `use: [ 'style-loader' ]`) is a shortcut to the loader property (i.e. `use: [ { loader: 'style-loader '} ]`). - -Loaders can be chained by passing multiple loaders, which will be applied from right to left (last to first configured). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - //... - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1 - } - }, - { - loader: 'less-loader', - options: { - noIeCompat: true - } - } - ] - } - ] - } -}; -``` - -See [UseEntry](#useentry) for details. - - -## `Condition` - -Conditions can be one of these: - -- A string: To match the input must start with the provided string. I. e. an absolute directory path, or absolute path to the file. -- A RegExp: It's tested with the input. -- A function: It's called with the input and must return a truthy value to match. -- An array of Conditions: At least one of the Conditions must match. -- An object: All properties must match. Each property has a defined behavior. - -`{ test: Condition }`: The Condition must match. The convention is to provide a RegExp or array of RegExps here, but it's not enforced. - -`{ include: Condition }`: The Condition must match. The convention is to provide a string or array of strings here, but it's not enforced. - -`{ exclude: Condition }`: The Condition must NOT match. The convention is to provide a string or array of strings here, but it's not enforced. - -`{ and: [Condition] }`: All Conditions must match. - -`{ or: [Condition] }`: Any Condition must match. - -`{ not: [Condition] }`: All Conditions must NOT match. - -__Example:__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - include: [ - path.resolve(__dirname, 'app/styles'), - path.resolve(__dirname, 'vendor/styles') - ] - } - ] - } -}; -``` - - -## `UseEntry` - -`object` - -It must have a `loader` property being a string. It is resolved relative to the configuration [`context`](/configuration/entry-context#context) with the loader resolving options ([resolveLoader](/configuration/resolve#resolveloader)). - -It can have an `options` property being a string or object. This value is passed to the loader, which should interpret it as loader options. - -For compatibility a `query` property is also possible, which is an alias for the `options` property. Use the `options` property instead. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - loader: 'css-loader', - options: { - modules: true - } - } - ] - } -}; -``` - -Note that webpack needs to generate a unique module identifier from the resource and all loaders including options. It tries to do this with a `JSON.stringify` of the options object. This is fine in 99.9% of cases, but may be not unique if you apply the same loaders with different options to the resource and the options have some stringified values. - -It also breaks if the options object cannot be stringified (i.e. circular JSON). Because of this you can have a `ident` property in the options object which is used as unique identifier. - - -## Module Contexts - -> Avoid using these options as they are __deprecated__ and will soon be removed. - -These options describe the default settings for the context created when a dynamic dependency is encountered. - -Example for an `unknown` dynamic dependency: `require`. - -Example for an `expr` dynamic dependency: `require(expr)`. - -Example for an `wrapped` dynamic dependency: `require('./templates/' + expr)`. - -Here are the available options with their [defaults](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js): - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - exprContextCritical: true, - exprContextRecursive: true, - exprContextRegExp: false, - exprContextRequest: '.', - unknownContextCritical: true, - unknownContextRecursive: true, - unknownContextRegExp: false, - unknownContextRequest: '.', - wrappedContextCritical: false, - wrappedContextRecursive: true, - wrappedContextRegExp: /.*/, - strictExportPresence: false // since webpack 2.3.0 - } -}; -``` - -T> You can use the `ContextReplacementPlugin` to modify these values for individual dependencies. This also removes the warning. - -A few use cases: - -- Warn for dynamic dependencies: `wrappedContextCritical: true`. -- `require(expr)` should include the whole directory: `exprContextRegExp: /^\.\//` -- `require('./templates/' + expr)` should not include subdirectories by default: `wrappedContextRecursive: false` -- `strictExportPresence` makes missing exports an error instead of warning - - -# Resolve - -These options change how modules are resolved. webpack provides reasonable defaults, but it is possible to change the resolving in detail. Have a look at [Module Resolution](/concepts/module-resolution) for more explanation of how the resolver works. - - -## `resolve` - -`object` - -Configure how modules are resolved. For example, when calling `import "lodash"` in ES2015, the `resolve` options can change where webpack goes to look for `"lodash"` (see [`modules`](#resolve-modules)). - - -### `resolve.alias` - -`object` - -Create aliases to `import` or `require` certain modules more easily. For example, to alias a bunch of commonly used `src/` folders: - -```js -module.exports = { - //... - resolve: { - alias: { - Utilities: path.resolve(__dirname, 'src/utilities/'), - Templates: path.resolve(__dirname, 'src/templates/') - } - } -}; -``` - -Now, instead of using relative paths when importing like so: - -```js -import Utility from '../../utilities/utility'; -``` - -you can use the alias: - -```js -import Utility from 'Utilities/utility'; -``` - -A trailing `$` can also be added to the given object's keys to signify an exact match: - -```js -module.exports = { - //... - resolve: { - alias: { - xyz$: path.resolve(__dirname, 'path/to/file.js') - } - } -}; -``` - -which would yield these results: - -```js -import Test1 from 'xyz'; // Exact match, so path/to/file.js is resolved and imported -import Test2 from 'xyz/file.js'; // Not an exact match, normal resolution takes place -``` - -The following table explains other cases: - -| `alias:` | `import "xyz"` | `import "xyz/file.js"` | -| ----------------------------------- | ------------------------------------- | ----------------------------------- | -| `{}` | `/abc/node_modules/xyz/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | error | -| `{ xyz$: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "./dir/file.js" }` | `/abc/dir/file.js` | error | -| `{ xyz$: "./dir/file.js" }` | `/abc/dir/file.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "/some/dir" }` | `/some/dir/index.js` | `/some/dir/file.js` | -| `{ xyz$: "/some/dir" }` | `/some/dir/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "./dir" }` | `/abc/dir/index.js` | `/abc/dir/file.js` | -| `{ xyz: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/modu/file.js` | -| `{ xyz$: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "modu/some/file.js" }` | `/abc/node_modules/modu/some/file.js` | error | -| `{ xyz: "modu/dir" }` | `/abc/node_modules/modu/dir/index.js` | `/abc/node_modules/dir/file.js` | -| `{ xyz: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/dir/file.js` | -| `{ xyz$: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/file.js` | - -`index.js` may resolve to another file if defined in the `package.json`. - -`/abc/node_modules` may resolve in `/node_modules` too. - - -### `resolve.aliasFields` - -`array` - -Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec). Default: - -```js -module.exports = { - //... - resolve: { - aliasFields: ['browser'] - } -}; -``` - - -### `resolve.cacheWithContext` - -`boolean` (since webpack 3.1.0) - -If unsafe cache is enabled, includes `request.context` in the cache key. This option is taken into account by the [`enhanced-resolve`](https://github.com/webpack/enhanced-resolve/) module. Since webpack 3.1.0 context in resolve caching is ignored when resolve or resolveLoader plugins are provided. This addresses a performance regression. - - -### `resolve.descriptionFiles` - -`array` - -The JSON files to use for descriptions. Default: - -```js -module.exports = { - //... - resolve: { - descriptionFiles: ['package.json'] - } -}; -``` - - -### `resolve.enforceExtension` - -`boolean` - -If `true`, it will not allow extension-less files. So by default `require('./foo')` works if `./foo` has a `.js` extension, but with this enabled only `require('./foo.js')` will work. Default: - -```js -module.exports = { - //... - resolve: { - enforceExtension: false - } -}; -``` - - -### `resolve.enforceModuleExtension` - -`boolean` - -Whether to require to use an extension for modules (e.g. loaders). Default: - -```js -module.exports = { - //... - resolve: { - enforceModuleExtension: false - } -}; -``` - - -### `resolve.extensions` - -`array` - -Automatically resolve certain extensions. This defaults to: - -```js -module.exports = { - //... - resolve: { - extensions: ['.wasm', '.mjs', '.js', '.json'] - } -}; -``` - -which is what enables users to leave off the extension when importing: - -```js -import File from '../path/to/file'; -``` - -W> Using this will __override the default array__, meaning that webpack will no longer try to resolve modules using the default extensions. For modules that are imported with their extension, e.g. `import SomeFile from "./somefile.ext"`, to be properly resolved, a string containing "\*" must be included in the array. - - -### `resolve.mainFields` - -`array` - -When importing from an npm package, e.g. `import * as D3 from "d3"`, this option will determine which fields in its `package.json` are checked. The default values will vary based upon the [`target`](/concepts/targets) specified in your webpack configuration. - -When the `target` property is set to `webworker`, `web`, or left unspecified: - - -```js -module.exports = { - //... - resolve: { - mainFields: ['browser', 'module', 'main'] - } -}; -``` - -For any other target (including `node`): - -```js -module.exports = { - //... - resolve: { - mainFields: ['module', 'main'] - } -}; -``` - -For example, the `package.json` of [D3](https://d3js.org/) contains these fields: - -```json -{ - "main": "build/d3.Node.js", - "browser": "build/d3.js", - "module": "index" -} -``` - -This means that when we `import * as D3 from "d3"` this will really resolve to the file in the `browser` property. The `browser` property takes precedence here because it's the first item in `mainFields`. Meanwhile, a Node.js application bundled by webpack will resolve by default to the file in the `module` field. - - -### `resolve.mainFiles` - -`array` - -The filename to be used while resolving directories. Default: - -```js -module.exports = { - //... - resolve: { - mainFiles: ['index'] - } -}; -``` - - -### `resolve.modules` - -`array` - -Tell webpack what directories should be searched when resolving modules. - -Absolute and relative paths can both be used, but be aware that they will behave a bit differently. - -A relative path will be scanned similarly to how Node scans for `node_modules`, by looking through the current directory as well as its ancestors (i.e. `./node_modules`, `../node_modules`, and on). - -With an absolute path, it will only search in the given directory. - -`resolve.modules` defaults to: - -```js -module.exports = { - //... - resolve: { - modules: ['node_modules'] - } -}; -``` - -If you want to add a directory to search in that takes precedence over `node_modules/`: - -```js -module.exports = { - //... - resolve: { - modules: [path.resolve(__dirname, 'src'), 'node_modules'] - } -}; -``` - - -### `resolve.unsafeCache` - -`regex` `array` `boolean` - -Enable aggressive, but __unsafe__, caching of modules. Passing `true` will cache everything. Default: - -```js -module.exports = { - //... - resolve: { - unsafeCache: true - } -}; -``` - -A regular expression, or an array of regular expressions, can be used to test file paths and only cache certain modules. For example, to only cache utilities: - -```js -module.exports = { - //... - resolve: { - unsafeCache: /src\/utilities/ - } -}; -``` - -W> Changes to cached paths may cause failure in rare cases. - - -### `resolve.plugins` - -A list of additional resolve plugins which should be applied. It allows plugins such as [`DirectoryNamedWebpackPlugin`](https://www.npmjs.com/package/directory-named-webpack-plugin). - -```js -module.exports = { - //... - resolve: { - plugins: [ - new DirectoryNamedWebpackPlugin() - ] - } -}; -``` - - -### `resolve.symlinks` - -`boolean` - -Whether to resolve symlinks to their symlinked location. - -When enabled, symlinked resources are resolved to their _real_ path, not their symlinked location. Note that this may cause module resolution to fail when using tools that symlink packages (like `npm link`). - -`resolve.symlinks` defaults to: - -```js -module.exports = { - //... - resolve: { - symlinks: true - } -}; -``` - - -### `resolve.cachePredicate` - -`function` - -A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. Default: - -```js -module.exports = { - //... - resolve: { - cachePredicate: function() { return true; } - } -}; -``` - - -## `resolveLoader` - -`object` - -This set of options is identical to the `resolve` property set above, but is used only to resolve webpack's [loader](/concepts/loaders) packages. Default: - -```js -module.exports = { - //... - resolveLoader: { - modules: [ 'node_modules' ], - extensions: [ '.js', '.json' ], - mainFields: [ 'loader', 'main' ] - } -}; -``` - -T> Note that you can use alias here and other features familiar from resolve. For example `{ txt: 'raw-loader' }` would shim `txt!templates/demo.txt` to use `raw-loader`. - - -### `resolveLoader.moduleExtensions` - -`array` - -The extensions/suffixes that are used when resolving loaders. Since version two, we [strongly recommend](/migrate/3/#automatic-loader-module-name-extension-removed) using the full name, e.g. `example-loader`, as much as possible for clarity. However, if you really wanted to exclude the `-loader` bit, i.e. just use `example`, you can use this option to do so: - -```js -module.exports = { - //... - resolveLoader: { - moduleExtensions: [ '-loader' ] - } -}; -``` - - -# Optimization - -Since version 4 webpack runs optimizations for you depending on the chosen [`mode`](/concepts/mode/), still all optimizations are available for manual configuration and overrides. - - -## `optimization.minimize` - -`boolean` - -Tell webpack to minimize the bundle using the [TerserPlugin](/plugins/terser-webpack-plugin/). - -This is `true` by default in `production` mode. - -__webpack.config.js__ - - -```js -module.exports = { - //... - optimization: { - minimize: false - } -}; -``` - -T> Learn how [mode](/concepts/mode/) works. - -## `optimization.minimizer` - -`[TerserPlugin]` - -Allows you to override the default minimizer by providing a different one or more customized [TerserPlugin](/plugins/terser-webpack-plugin/) instances. - -__webpack.config.js__ - - -```js -const TerserPlugin = require('terser-webpack-plugin'); - -module.exports = { - //... - optimization: { - minimizer: [ - new TerserPlugin({ /* your config */ }) - ] - } -}; -``` - -## `optimization.splitChunks` - -`object` - -By default webpack v4+ provides new common chunks strategies out of the box for dynamically imported modules. See available options for configuring this behavior in the [SplitChunksPlugin](/plugins/split-chunks-plugin/) page. - -## `optimization.runtimeChunk` - -`object` `string` `boolean` - -Setting `optimization.runtimeChunk` to `true` or `"multiple"` adds an additional chunk to each entrypoint containing only the runtime. This setting is an alias for: - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: entrypoint => `runtime~${entrypoint.name}` - } - } -}; -``` - -The value `"single"` instead creates a runtime file to be shared for all generated chunks. This setting is an alias for: - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: 'runtime' - } - } -}; -``` - -By setting `optimization.runtimeChunk` to `object` it is only possible to provide the `name` property which stands for the name or name factory for the runtime chunks. - -Default is `false`: each entry chunk embeds runtime. - -W> Imported modules are initialized for each runtime chunk separately, so if you include multiple entry points on a page, beware of this behavior. You will probably want to set it to `single` or use another configuration that allows you to only have one runtime instance. - -__webpack.config.js__ - - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: entrypoint => `runtimechunk~${entrypoint.name}` - } - } -}; -``` - -## `optimization.noEmitOnErrors` - -`boolean` - -Use the `optimization.noEmitOnErrors` to skip the emitting phase whenever there are errors while compiling. This ensures that no erroring assets are emitted. The `emitted` flag in the stats is `false` for all assets. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - noEmitOnErrors: true - } -}; -``` - -W> If you are using webpack [CLI](/api/cli/), the webpack process will not exit with an error code while this plugin is enabled. If you want webpack to "fail" when using the CLI, please check out the [`bail` option](/api/cli/#advanced-options). - -## `optimization.namedModules` - -`boolean: false` - -Tells webpack to use readable module identifiers for better debugging. When `optimization.namedModules` is not set in webpack config, webpack will enable it by default for [mode](/concepts/mode/) `development` and disable for [mode](/concepts/mode/) `production`. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - namedModules: true - } -}; -``` - -## `optimization.namedChunks` - -`boolean: false` - -Tells webpack to use readable chunk identifiers for better debugging. This option is enabled by default for [mode](/concepts/mode/) `development` and disabled for [mode](/concepts/mode/) `production` if no option is provided in webpack config. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - namedChunks: true - } -}; -``` - -## `optimization.moduleIds` - -`bool: false` `string: natural, named, hashed, size, total-size` - -Tells webpack which algorithm to use when choosing module ids. Setting `optimization.moduleIds` to `false` tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin. By default `optimization.moduleIds` is set to `false`. - -The following string values are supported: - -Option | Description ---------------------- | ----------------------- -`natural` | Numeric ids in order of usage. -`named` | Readable ids for better debugging. -`hashed` | Short hashes as ids for better long term caching. -`size` | Numeric ids focused on minimal initial download size. -`total-size` | numeric ids focused on minimal total download size. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - moduleIds: 'hashed' - } -}; -``` - -## `optimization.nodeEnv` - -`string` `bool: false` - -Tells webpack to set `process.env.NODE_ENV` to a given string value. `optimization.nodeEnv` uses [DefinePlugin](/plugins/define-plugin/) unless set to `false`. `optimization.nodeEnv` __defaults__ to [mode](/concepts/mode/) if set, else falls back to `"production"`. - -Possible values: - -- any string: the value to set `process.env.NODE_ENV` to. -- false: do not modify/set the value of `process.env.NODE_ENV`. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - nodeEnv: 'production' - } -}; -``` - -## `optimization.mangleWasmImports` - -`bool: false` - -When set to `true` tells webpack to reduce the size of WASM by changing imports to shorter strings. It mangles module and export names. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - mangleWasmImports: true - } -}; -``` - -## `optimization.removeAvailableModules` - -`bool: true` - -Tells webpack to detect and remove modules from chunks when these modules are already included in all parents. Setting `optimization.removeAvailableModules` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - removeAvailableModules: false - } -}; -``` - -## `optimization.removeEmptyChunks` - -`bool: true` - -Tells webpack to detect and remove chunks which are empty. Setting `optimization.removeEmptyChunks` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - removeEmptyChunks: false - } -}; -``` - -## `optimization.mergeDuplicateChunks` - -`bool: true` - -Tells webpack to merge chunks which contain the same modules. Setting `optimization.mergeDuplicateChunks` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - mergeDuplicateChunks: false - } -}; -``` - -## `optimization.flagIncludedChunks` - -`bool` - -Tells webpack to determine and flag chunks which are subsets of other chunks in a way that subsets don’t have to be loaded when the bigger chunk has been already loaded. By default `optimization.flagIncludedChunks` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - flagIncludedChunks: true - } -}; -``` - -## `optimization.occurrenceOrder` - -`bool` - -Tells webpack to figure out an order of modules which will result in the smallest initial bundle. By default `optimization.occurrenceOrder` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - occurrenceOrder: false - } -}; -``` - -## `optimization.providedExports` - -`bool` - -Tells webpack to figure out which exports are provided by modules to generate more efficient code for `export * from ...`. By default `optimization.providedExports` is enabled. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - providedExports: false - } -}; -``` - -## `optimization.usedExports` - -`bool` - -Tells webpack to determine used exports for each module. This depends on [`optimization.providedExports`](#optimization-occurrenceorder). Information collected by `optimization.usedExports` is used by other optimizations or code generation i.e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible. -Dead code elimination in minimizers will benefit from this and can remove unused exports. -By default `optimization.usedExports` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - usedExports: true - } -}; -``` - -## `optimization.concatenateModules` - -`bool` - -Tells webpack to find segments of the module graph which can be safely concatenated into a single module. Depends on [`optimization.providedExports`](#optimization-providedexports) and [`optimization.usedExports`](#optimization-usedexports). -By default `optimization.concatenateModules` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - concatenateModules: true - } -}; -``` - -## `optimization.sideEffects` - -`bool` - -Tells webpack to recognise the [`sideEffects`](https://github.com/webpack/webpack/blob/master/examples/side-effects/README.md) flag in `package.json` or rules to skip over modules which are flagged to contain no side effects when exports are not used. - -__package.json__ - -``` json -{ - "name": "awesome npm module", - "version": "1.0.0", - "sideEffects": false -} -``` - -T> Please note that `sideEffects` should be in the npm module's `package.json` file and doesn't mean that you need to set `sideEffects` to `false` in your own project's `package.json` which requires that big module. - -`optimization.sideEffects` depends on [`optimization.providedExports`](#optimization-providedexports) to be enabled. This dependency has a build time cost, but eliminating modules has positive impact on performance because of less code generation. Effect of this optimization depends on your codebase, try it for possible performance wins. - -By default `optimization.sideEffects` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - sideEffects: true - } -}; -``` - -## `optimization.portableRecords` - -`bool` - -`optimization.portableRecords` tells webpack to generate records with relative paths to be able to move the context folder. - -By default `optimization.portableRecords` is disabled. Automatically enabled if at least one of the records options provided to webpack config: [`recordsPath`](/configuration/other-options/#recordspath), [`recordsInputPath`](/configuration/other-options/#recordsinputpath), [`recordsOutputPath`](/configuration/other-options/#recordsoutputpath). - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - portableRecords: true - } -}; -``` - - -# Plugins - -The `plugins` option is used to customize the webpack build process in a variety of ways. webpack comes with a variety built-in plugins available under `webpack.[plugin-name]`. See [Plugins page](/plugins) for a list of plugins and documentation but note that there are a lot more out in the community. - -T> Note: This page only discusses using plugins, however if you are interested in writing your own please visit [Writing a Plugin](/development/how-to-write-a-plugin/). - - -## `plugins` - -`array` - -A list of webpack plugins. For example, [`DefinePlugin`](/plugins/define-plugin/) allows you to create global constants which can be configured at compile time. This can be useful for allowing different behavior between development builds and release builds. - -```js -module.exports = { - //... - plugins: [ - new webpack.DefinePlugin({ - // Definitions... - }) - ] -}; -``` - -A more complex example, using multiple plugins, might look something like this: - -```js -var webpack = require('webpack'); -// importing plugins that do not come by default in webpack -var ExtractTextPlugin = require('extract-text-webpack-plugin'); -var DashboardPlugin = require('webpack-dashboard/plugin'); - -// adding plugins to your configuration -module.exports = { - //... - plugins: [ - new ExtractTextPlugin({ - filename: 'build.min.css', - allChunks: true, - }), - new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), - // compile time plugins - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': '"production"', - }), - // webpack-dev-server enhancement plugins - new DashboardPlugin(), - new webpack.HotModuleReplacementPlugin(), - ] -}; -``` - - -# DevServer - -[webpack-dev-server](https://github.com/webpack/webpack-dev-server) can be used to quickly develop an application. See the [development guide](/guides/development/) to get started. - -This page describes the options that affect the behavior of webpack-dev-server (short: dev-server). - -T> Options that are compatible with [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) have 🔑 next to them. - - -## `devServer` - -`object` - -This set of options is picked up by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) and can be used to change its behavior in various ways. Here's a simple example that gzips and serves everything from our `dist/` directory in the project root: - -__webpack.config.js__ - -```javascript -var path = require('path'); - -module.exports = { - //... - devServer: { - contentBase: path.join(__dirname, 'dist'), - compress: true, - port: 9000 - } -}; -``` - -When the server is started, there will be a message prior to the list of resolved modules: - -```bash -http://localhost:9000/ -webpack output is served from /build/ -Content not from webpack is served from /path/to/dist/ -``` - -that will give some background on where the server is located and what it's serving. - -If you're using dev-server through the Node.js API, the options in `devServer` will be ignored. Pass the options as a second parameter instead: `new WebpackDevServer(compiler, {...})`. [See here](https://github.com/webpack/webpack-dev-server/tree/master/examples/api/simple) for an example of how to use webpack-dev-server through the Node.js API. - -W> Be aware that when [exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) only the `devServer` options for the first configuration will be taken into account and used for all the configurations in the array. - -T> If you're having trouble, navigating to the `/webpack-dev-server` route will show where files are served. For example, `http://localhost:9000/webpack-dev-server`. - -## `devServer.after` - -`function (app, server)` - -Provides the ability to execute custom middleware after all other middleware -internally within the server. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - after: function(app, server) { - // do fancy stuff - } - } -}; -``` - -## `devServer.allowedHosts` - -`array` - -This option allows you to whitelist services that are allowed to access the dev server. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - allowedHosts: [ - 'host.com', - 'subdomain.host.com', - 'subdomain2.host.com', - 'host2.com' - ] - } -}; -``` - -Mimicking django's `ALLOWED_HOSTS`, a value beginning with `.` can be used as a subdomain wildcard. `.host.com` will match `host.com`, `www.host.com`, and any other subdomain of `host.com`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - // this achieves the same effect as the first example - // with the bonus of not having to update your config - // if new subdomains need to access the dev server - allowedHosts: [ - '.host.com', - 'host2.com' - ] - } -}; -``` - -To use this option with the CLI pass the `--allowed-hosts` option a comma-delimited string. - -```bash -webpack-dev-server --entry /entry/file --output-path /output/path --allowed-hosts .host.com,host2.com -``` - -## `devServer.before` - -`function (app, server)` - -Provides the ability to execute custom middleware prior to all other middleware -internally within the server. This could be used to define custom handlers, for -example: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - before: function(app, server) { - app.get('/some/path', function(req, res) { - res.json({ custom: 'response' }); - }); - } - } -}; -``` - -## `devServer.bonjour` - -This option broadcasts the server via [ZeroConf](http://www.zeroconf.org/) networking on start - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - bonjour: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --bonjour -``` - - -## `devServer.clientLogLevel` - -`string: 'none' | 'info' | 'error' | 'warning'` - -When using _inline mode_, the console in your DevTools will show you messages e.g. before reloading, before an error or when [Hot Module Replacement](/concepts/hot-module-replacement/) is enabled. Defaults to `info`. - -`devServer.clientLogLevel` may be too verbose, you can turn logging off by setting it to `'none'`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - clientLogLevel: 'none' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --client-log-level none -``` - -## `devServer.color` - CLI only - -`boolean` - -Enables/Disables colors on the console. - -```bash -webpack-dev-server --color -``` - - -## `devServer.compress` - -`boolean` - -Enable [gzip compression](https://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/) for everything served: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - compress: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --compress -``` - - -## `devServer.contentBase` - -`boolean: false` `string` `[string]` `number` - -Tell the server where to serve content from. This is only necessary if you want to serve static files. [`devServer.publicPath`](#devserver-publicpath-) will be used to determine where the bundles should be served from, and takes precedence. - -T> It is recommended to use an absolute path. - -By default it will use your current working directory to serve content. To disable `contentBase` set it to `false`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - contentBase: path.join(__dirname, 'public') - } -}; -``` - -It is also possible to serve from multiple directories: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - contentBase: [path.join(__dirname, 'public'), path.join(__dirname, 'assets')] - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --content-base /path/to/content/dir -``` - - -## `devServer.disableHostCheck` - -`boolean` - -When set to `true` this option bypasses host checking. __THIS IS NOT RECOMMENDED__ as apps that do not check the host are vulnerable to DNS rebinding attacks. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - disableHostCheck: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --disable-host-check -``` - - -## `devServer.filename` 🔑 - -`string` - -This option lets you reduce the compilations in [lazy mode](#devserver-lazy-). -By default in [lazy mode](#devserver-lazy-), every request results in a new compilation. With `filename`, it's possible to only compile when a certain file is requested. - -If [`output.filename`](/configuration/output/#output-filename) is set to `'bundle.js'` and `devServer.filename` is used like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: 'bundle.js' - }, - devServer: { - lazy: true, - filename: 'bundle.js' - } -}; -``` - -It will now only compile the bundle when `/bundle.js` is requested. - -T> `filename` has no effect when used without [lazy mode](#devserver-lazy-). - - -## `devServer.headers` 🔑 - -`object` - -Adds headers to all responses: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - headers: { - 'X-Custom-Foo': 'bar' - } - } -}; -``` - - -## `devServer.historyApiFallback` - -`boolean` `object` - -When using the [HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/API/History), the `index.html` page will likely have to be served in place of any `404` responses. `devServer.historyApiFallback` is disabled by default. Enable it by passing: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: true - } -}; -``` - -By passing an object this behavior can be controlled further using options like `rewrites`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: { - rewrites: [ - { from: /^\/$/, to: '/views/landing.html' }, - { from: /^\/subpage/, to: '/views/subpage.html' }, - { from: /./, to: '/views/404.html' } - ] - } - } -}; -``` - -When using dots in your path (common with Angular), you may need to use the `disableDotRule`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: { - disableDotRule: true - } - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --history-api-fallback -``` - -For more options and information, see the [connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback) documentation. - - -## `devServer.host` - -`string` - -Specify a host to use. By default this is `localhost`. If you want your server to be accessible externally, specify it like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - host: '0.0.0.0' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --host 0.0.0.0 -``` - - -## `devServer.hot` - -`boolean` - -Enable webpack's [Hot Module Replacement](/concepts/hot-module-replacement/) feature: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - hot: true - } -}; -``` - -T> Note that [`webpack.HotModuleReplacementPlugin`](/plugins/hot-module-replacement-plugin/) is required to fully enable HMR. If `webpack` or `webpack-dev-server` are launched with the `--hot` option, this plugin will be added automatically, so you may not need to add this to your `webpack.config.js`. See the [HMR concepts page](/concepts/hot-module-replacement/) for more information. - - -## `devServer.hotOnly` - -`boolean` - -Enables Hot Module Replacement (see [`devServer.hot`](#devserver-hot)) without page refresh as fallback in case of build failures. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - hotOnly: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --hot-only -``` - - -## `devServer.https` - -`boolean` `object` - -By default dev-server will be served over HTTP. It can optionally be served over HTTP/2 with HTTPS: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - https: true - } -}; -``` - -With the above setting a self-signed certificate is used, but you can provide your own: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - https: { - key: fs.readFileSync('/path/to/server.key'), - cert: fs.readFileSync('/path/to/server.crt'), - ca: fs.readFileSync('/path/to/ca.pem'), - } - } -}; -``` - -This object is passed straight to Node.js HTTPS module, so see the [HTTPS documentation](https://nodejs.org/api/https.html) for more information. - -Usage via the CLI - -```bash -webpack-dev-server --https -``` - -To pass your own certificate via the CLI use the following options - -```bash -webpack-dev-server --https --key /path/to/server.key --cert /path/to/server.crt --cacert /path/to/ca.pem -``` - -## `devServer.index` - -`string` - -The filename that is considered the index file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - index: 'index.html' - } -}; -``` - - -## `devServer.info` - CLI only - -`boolean` - -Output cli information. It is enabled by default. - -```bash -webpack-dev-server --info=false -``` - - -## `devServer.inline` - -`boolean` - -Toggle between the dev-server's two different modes. By default the application will be served with _inline mode_ enabled. This means that a script will be inserted in your bundle to take care of live reloading, and build messages will appear in the browser console. - -It is also possible to use __iframe mode__, which uses an `<iframe>` under a notification bar with messages about the build. To switch to __iframe mode__: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - inline: false - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --inline=false -``` - -T> Inline mode is recommended for [Hot Module Replacement](/plugins/hot-module-replacement-plugin/) as it includes an HMR trigger from the websocket. Polling mode can be used as an alternative, but requires an additional entry point, `'webpack/hot/poll?1000'`. - - -## `devServer.lazy` 🔑 - -`boolean` - -When `devServer.lazy` is enabled, the dev-server will only compile the bundle when it gets requested. This means that webpack will not watch any file changes. We call this __lazy mode__. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - lazy: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --lazy -``` - -T> [`watchOptions`](#devserver-watchoptions-) will have no effect when used with __lazy mode__. - -T> If you use the CLI, make sure __inline mode__ is disabled. - - -## `devServer.noInfo` 🔑 - -`boolean` - -Tells dev-server to supress messages like the webpack bundle information. Errors and warnings will still be shown. `devServer.noInfo` is disabled by default. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - noInfo: true - } -}; -``` - - -## `devServer.open` - -`boolean` `string` - -Tells dev-server to open the browser after server had been started. Disabled by default. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - open: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --open -``` - -If no browser is provided (as shown above), your default browser will be used. To specify a different browser, just pass its name: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - open: 'Chrome' - } -}; -``` - -And via the CLI - -```bash -webpack-dev-server --open 'Chrome' -``` - -T> The browser application name is platform dependent. Don't hard code it in reusable modules. For example, `'Chrome'` is Google Chrome on macOS, `'google-chrome'` on Linux and `'chrome'` on Windows. - - -## `devServer.openPage` - -`string` - -Specify a page to navigate to when opening the browser. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - openPage: '/different/page' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --open-page "/different/page" -``` - - -## `devServer.overlay` - -`boolean` `object: { boolean errors, boolean warnings }` - -Shows a full-screen overlay in the browser when there are compiler errors or warnings. Disabled by default. If you want to show only compiler errors: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - overlay: true - } -}; -``` - -If you want to show warnings as well as errors: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - overlay: { - warnings: true, - errors: true - } - } -}; -``` - - -## `devServer.pfx` - -`string` - -When used via the CLI, a path to an SSL .pfx file. If used in options, it should be the bytestream of the .pfx file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - pfx: '/path/to/file.pfx' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --pfx /path/to/file.pfx -``` - - -## `devServer.pfxPassphrase` - -`string` - -The passphrase to a SSL PFX file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - pfxPassphrase: 'passphrase' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --pfx-passphrase passphrase -``` - - -## `devServer.port` - -`number` - -Specify a port number to listen for requests on: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - port: 8080 - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --port 8080 -``` - - -## `devServer.proxy` - -`object` `[object, function]` - -Proxying some URLs can be useful when you have a separate API backend development server and you want to send API requests on the same domain. - -The dev-server makes use of the powerful [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) package. Check out its [documentation](https://github.com/chimurai/http-proxy-middleware#options) for more advanced usages. Note that some of `http-proxy-middleware`'s features do not require a `target` key, e.g. its `router` feature, but you will still need to include a `target` key in your config here, otherwise `webpack-dev-server` won't pass it along to `http-proxy-middleware`). - -With a backend on `localhost:3000`, you can use this to enable proxying: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': 'http://localhost:3000' - } - } -}; -``` - -A request to `/api/users` will now proxy the request to `http://localhost:3000/api/users`. - -If you don't want `/api` to be passed along, we need to rewrite the path: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'http://localhost:3000', - pathRewrite: {'^/api' : ''} - } - } - } -}; -``` - -A backend server running on HTTPS with an invalid certificate will not be accepted by default. If you want to, modify your config like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'https://other-server.example.com', - secure: false - } - } - } -}; -``` - -Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a function. - -In the function you get access to the request, response and proxy options. It must return either `false` or a path that will be served instead of continuing to proxy the request. - -E.g. for a browser request, you want to serve a HTML page, but for an API request you want to proxy it. You could do something like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'http://localhost:3000', - bypass: function(req, res, proxyOptions) { - if (req.headers.accept.indexOf('html') !== -1) { - console.log('Skipping proxy for browser request.'); - return '/index.html'; - } - } - } - } - } -}; -``` - -If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a `context` property: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: [{ - context: ['/auth', '/api'], - target: 'http://localhost:3000', - }] - } -}; -``` - -Note that requests to root won't be proxied by default. To enable root proxying, the `devServer.index` option should be specified as a falsy value: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - index: '', // specify to enable root proxying - host: '...', - contentBase: '...', - proxy: { - context: () => true, - target: 'http://localhost:1234' - } - } -}; -``` - -The origin of the host header is kept when proxying by default, you can set `changeOrigin` to `true` to override this behaviour. It is useful in some cases like using [name-based virtual hosted sites](https://en.wikipedia.org/wiki/Virtual_hosting#Name-based). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': 'http://localhost:3000', - changeOrigin: true - } - } -}; -``` - -## `devServer.progress` - CLI only - -`boolean` - -Output running progress to console. - -```bash -webpack-dev-server --progress -``` - - -## `devServer.public` - -`string` - -When using _inline mode_ and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on `window.location`, but if that fails you'll need to use this. - -For example, the dev-server is proxied by nginx, and available on `myapp.test`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - public: 'myapp.test:80' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --public myapp.test:80 -``` - - -## `devServer.publicPath` 🔑 - -`string` - -The bundled files will be available in the browser under this path. - -Imagine that the server is running under `http://localhost:8080` and [`output.filename`](/configuration/output/#output-filename) is set to `bundle.js`. By default the `devServer.publicPath` is `'/'`, so your bundle is available as `http://localhost:8080/bundle.js`. - -Change `devServer.publicPath` to put bundle under specific directory: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - publicPath: '/assets/' - } -}; -``` - -The bundle will now be available as `http://localhost:8080/assets/bundle.js`. - -T> Make sure `devServer.publicPath` always starts and ends with a forward slash. - -It is also possible to use a full URL. This is necessary for [Hot Module Replacement](/concepts/hot-module-replacement/). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - publicPath: 'http://localhost:8080/assets/' - } -}; -``` - -The bundle will also be available as `http://localhost:8080/assets/bundle.js`. - -T> It is recommended that `devServer.publicPath` is the same as [`output.publicPath`](/configuration/output/#output-publicpath). - - -## `devServer.quiet` 🔑 - -`boolean` - -With `devServer.quiet` enabled, nothing except the initial startup information will be written to the console. This also means that errors or warnings from webpack are not visible. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - quiet: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --quiet -``` - - -## `devServer.setup` - -`function (app, server)` - -W> This option is __deprecated__ in favor of [`devServer.before`](#devserver-before) and will be removed in v3.0.0. - -Here you can access the Express app object and add your own custom middleware to it. -For example, to define custom handlers for some paths: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - setup: function(app, server) { - app.get('/some/path', function(req, res) { - res.json({ custom: 'response' }); - }); - } - } -}; -``` - - -## `devServer.socket` - -`string` - -The Unix socket to listen to (instead of a host). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - socket: 'socket' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --socket socket -``` - - -## `devServer.staticOptions` - -It is possible to configure advanced options for serving static files from `contentBase`. See the [Express documentation](http://expressjs.com/en/4x/api.html#express.static) for the possible options. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - staticOptions: { - redirect: false - } - } -}; -``` - -T> This only works when using [`devServer.contentBase`](#devserver-contentbase) as a `string`. - - -## `devServer.stats` 🔑 - -`string: 'none' | 'errors-only' | 'minimal' | 'normal' | 'verbose'` `object` - -This option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you want some bundle information, but not all of it. - -To show only errors in your bundle: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - stats: 'errors-only' - } -}; -``` - -For more information, see the [__stats documentation__](/configuration/stats/). - -T> This option has no effect when used with `quiet` or `noInfo`. - - -## `devServer.stdin` - CLI only - -`boolean` - -This option closes the server when stdin ends. - -```bash -webpack-dev-server --stdin -``` - - -## `devServer.useLocalIp` - -`boolean` - -This option lets the browser open with your local IP. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - useLocalIp: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --useLocalIp -``` - - -## `devServer.watchContentBase` - -`boolean` - -Tell dev-server to watch the files served by the [`devServer.contentBase`](#devserver-contentbase) option. It is disabled by default. When enabled, file changes will trigger a full page reload. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - watchContentBase: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --watch-content-base -``` - - -## `devServer.watchOptions` 🔑 - -`object` - -Control options related to watching the files. - -webpack uses the file system to get notified of file changes. In some cases this does not work. For example, when using Network File System (NFS). [Vagrant](https://www.vagrantup.com/) also has a lot of problems with this. In these cases, use polling: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - watchOptions: { - poll: true - } - } -}; -``` - -If this is too heavy on the file system, you can change this to an integer to set the interval in milliseconds. - -See [WatchOptions](/configuration/watch/) for more options. - - -# Devtool - -This option controls if and how source maps are generated. - -Use the [`SourceMapDevToolPlugin`](/plugins/source-map-dev-tool-plugin) for a more fine grained configuration. See the [`source-map-loader`](/loaders/source-map-loader) to deal with existing source maps. - - -## `devtool` - -`string` `false` - -Choose a style of [source mapping](http://blog.teamtreehouse.com/introduction-source-maps) to enhance the debugging process. These values can affect build and rebuild speed dramatically. - -T> The webpack repository contains an [example showing the effect of all `devtool` variants](https://github.com/webpack/webpack/tree/master/examples/source-map). Those examples will likely help you to understand the differences. - -T> Instead of using the `devtool` option you can also use `SourceMapDevToolPlugin`/`EvalSourceMapDevToolPlugin` directly as it has more options. Never use both the `devtool` option and plugin together. The `devtool` option adds the plugin internally so you would end up with the plugin applied twice. - -devtool | build | rebuild | production | quality ------------------------------- | ----- | ------- | ---------- | ----------------------------- -(none) | +++ | +++ | yes | bundled code -eval | +++ | +++ | no | generated code -cheap-eval-source-map | + | ++ | no | transformed code (lines only) -cheap-module-eval-source-map | o | ++ | no | original source (lines only) -eval-source-map | -- | + | no | original source -cheap-source-map | + | o | yes | transformed code (lines only) -cheap-module-source-map | o | - | yes | original source (lines only) -inline-cheap-source-map | + | o | no | transformed code (lines only) -inline-cheap-module-source-map | o | - | no | original source (lines only) -source-map | -- | -- | yes | original source -inline-source-map | -- | -- | no | original source -hidden-source-map | -- | -- | yes | original source -nosources-source-map | -- | -- | yes | without source content - -T> `+++` super fast, `++` fast, `+` pretty fast, `o` medium, `-` pretty slow, `--` slow - -Some of these values are suited for development and some for production. For development you typically want fast Source Maps at the cost of bundle size, but for production you want separate Source Maps that are accurate and support minimizing. - -W> There are some issues with Source Maps in Chrome. [We need your help!](https://github.com/webpack/webpack/issues/3165). - -T> See [`output.sourceMapFilename`](/configuration/output#output-sourcemapfilename) to customize the filenames of generated Source Maps. - - -### Qualities - -`bundled code` - You see all generated code as a big blob of code. You don't see modules separated from each other. - -`generated code` - You see each module separated from each other, annotated with module names. You see the code generated by webpack. Example: Instead of `import {test} from "module"; test();` you see something like `var module__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); module__WEBPACK_IMPORTED_MODULE_1__.a();`. - -`transformed code` - You see each module separated from each other, annotated with module names. You see the code before webpack transforms it, but after Loaders transpile it. Example: Instead of `import {test} from "module"; class A extends test {}` you see something like `import {test} from "module"; var A = function(_test) { ... }(test);` - -`original source` - You see each module separated from each other, annotated with module names. You see the code before transpilation, as you authored it. This depends on Loader support. - -`without source content` - Contents for the sources are not included in the Source Maps. Browsers usually try to load the source from the webserver or filesystem. You have to make sure to set [`output.devtoolModuleFilenameTemplate`](/configuration/output/#output-devtoolmodulefilenametemplate) correctly to match source urls. - -`(lines only)` - Source Maps are simplified to a single mapping per line. This usually means a single mapping per statement (assuming you author is this way). This prevents you from debugging execution on statement level and from settings breakpoints on columns of a line. Combining with minimizing is not possible as minimizers usually only emit a single line. - - -### Development - -The following options are ideal for development: - -`eval` - Each module is executed with `eval()` and `//@ sourceURL`. This is pretty fast. The main disadvantage is that it doesn't display line numbers correctly since it gets mapped to transpiled code instead of the original code (No Source Maps from Loaders). - -`eval-source-map` - Each module is executed with `eval()` and a SourceMap is added as a DataUrl to the `eval()`. Initially it is slow, but it provides fast rebuild speed and yields real files. Line numbers are correctly mapped since it gets mapped to the original code. It yields the best quality SourceMaps for development. - -`cheap-eval-source-map` - Similar to `eval-source-map`, each module is executed with `eval()`. It is "cheap" because it doesn't have column mappings, it only maps line numbers. It ignores SourceMaps from Loaders and only display transpiled code similar to the `eval` devtool. - -`cheap-module-eval-source-map` - Similar to `cheap-eval-source-map`, however, in this case Source Maps from Loaders are processed for better results. However Loader Source Maps are simplified to a single mapping per line. - -### Special cases - -The following options are not ideal for development nor production. They are needed for some special cases, i. e. for some 3rd party tools. - -`inline-source-map` - A SourceMap is added as a DataUrl to the bundle. - -`cheap-source-map` - A SourceMap without column-mappings ignoring loader Source Maps. - -`inline-cheap-source-map` - Similar to `cheap-source-map` but SourceMap is added as a DataUrl to the bundle. - -`cheap-module-source-map` - A SourceMap without column-mappings that simplifies loader Source Maps to a single mapping per line. - -`inline-cheap-module-source-map` - Similar to `cheap-module-source-map` but SourceMap is added as a DataUrl to the bundle. - - -### Production - -These options are typically used in production: - -`(none)` (Omit the `devtool` option) - No SourceMap is emitted. This is a good option to start with. - -`source-map` - A full SourceMap is emitted as a separate file. It adds a reference comment to the bundle so development tools know where to find it. - -W> You should configure your server to disallow access to the Source Map file for normal users! - -`hidden-source-map` - Same as `source-map`, but doesn't add a reference comment to the bundle. Useful if you only want SourceMaps to map error stack traces from error reports, but don't want to expose your SourceMap for the browser development tools. - -W> You should not deploy the Source Map file to the webserver. Instead only use it for error report tooling. - -`nosources-source-map` - A SourceMap is created without the `sourcesContent` in it. It can be used to map stack traces on the client without exposing all of the source code. You can deploy the Source Map file to the webserver. - -W> It still exposes filenames and structure for decompiling, but it doesn't expose the original code. - -T> When using the `terser-webpack-plugin` you must provide the `sourceMap: true` option to enable SourceMap support. - - -# Target - -webpack can compile for multiple environments or _targets_. To understand what a `target` is in detail, read through [the targets concept page](/concepts/targets/). - -## `target` - -`string | function (compiler)` - -Instructs webpack to target a specific environment. - - -### `string` - -The following string values are supported via [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js): - -Option | Description ---------------------- | ----------------------- -`async-node` | Compile for usage in a Node.js-like environment (uses `fs` and `vm` to load chunks asynchronously) -`electron-main` | Compile for [Electron](https://electronjs.org/) for main process. -`electron-renderer` | Compile for [Electron](https://electronjs.org/) for renderer process, providing a target using `JsonpTemplatePlugin`, `FunctionModulePlugin` for browser environments and `NodeTargetPlugin` and `ExternalsPlugin` for CommonJS and Electron built-in modules. -`node` | Compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks) -`node-webkit` | Compile for usage in WebKit and uses JSONP for chunk loading. Allows importing of built-in Node.js modules and [`nw.gui`](http://docs.nwjs.io/en/latest/) (experimental) -`web` | Compile for usage in a browser-like environment __(default)__ -`webworker` | Compile as WebWorker - -For example, when the `target` is set to `"electron-main"`, webpack includes multiple electron specific variables. For more information on which templates and externals are used, you can refer to webpack's [source code](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js#L148-L183). - - -### `function` - -If a function is passed, then it will be called with the compiler as a parameter. Set it to a function if none of the predefined targets from the list above meet your needs. - -For example, if you don't want any of the plugins they applied: - -```js -const options = { - target: () => undefined -}; -``` - -Or you can apply specific plugins you want: - -```js -const webpack = require('webpack'); - -const options = { - target: (compiler) => { - compiler.apply( - new webpack.JsonpTemplatePlugin(options.output), - new webpack.LoaderTargetPlugin('web') - ); - } -}; -``` - - -# Watch and WatchOptions - -webpack can watch files and recompile whenever they change. This page explains how to enable this and a couple of tweaks you can make if watching does not work properly for you. - - -## `watch` - -`boolean` - -Turn on watch mode. This means that after the initial build, webpack will continue to watch for changes in any of the resolved files. Watch mode is turned off by default: - -```js -module.exports = { - //... - watch: false -}; -``` - -T> In webpack-dev-server and webpack-dev-middleware watch mode is enabled by default. - - -## `watchOptions` - -`object` - -A set of options used to customize watch mode: - -```js -module.exports = { - //... - watchOptions: { - aggregateTimeout: 300, - poll: 1000 - } -}; -``` - - -## `watchOptions.aggregateTimeout` - -`number` - -Add a delay before rebuilding once the first file changed. This allows webpack to aggregate any other changes made during this time period into one rebuild. Pass a value in milliseconds: - -```js -module.exports = { - //... - watchOptions: { - aggregateTimeout: 300 // The default - } -}; -``` - - -## `watchOptions.ignored` - -For some systems, watching many file systems can result in a lot of CPU or memory usage. It is possible to exclude a huge folder like `node_modules`: - -```js -module.exports = { - //... - watchOptions: { - ignored: /node_modules/ - } -}; -``` - -It is also possible to have and use multiple [anymatch](https://github.com/micromatch/anymatch) patterns: - -```js -module.exports = { - //... - watchOptions: { - ignored: ['files/**/*.js', 'node_modules'] - } -}; -``` - -T> If you use `require.context`, webpack will watch your entire directory. You will need to ignore files and/or directories so that unwanted changes will not trigger a rebuild. - - -## `watchOptions.poll` - -`boolean` `number` - -Turn on [polling](https://whatis.techtarget.com/definition/polling) by passing `true`, or specifying a poll interval in milliseconds: - -```js -module.exports = { - //... - watchOptions: { - poll: 1000 // Check for changes every second - } -}; -``` - -T> If watching does not work for you, try out this option. Watching does not work with NFS and machines in VirtualBox. - - -## `info-verbosity` - -`string`: `none` `info` `verbose` - -Controls verbosity of the lifecycle messaging, e.g. the `Started watching files...` log. Setting `info-verbosity` to `verbose` will also message to console at the beginning and the end of incremental build. `info-verbosity` is set to `info` by default. - -```bash -webpack --watch --info-verbosity verbose -``` - - -## Troubleshooting - -If you are experiencing any issues, please see the following notes. There are a variety of reasons why webpack might miss a file change. - -### Changes Seen But Not Processed - -Verify that webpack is not being notified of changes by running webpack with the --progress flag. If progress shows on save but no files are outputted, it is likely a configuration issue, not a file watching issue. - -```bash -webpack --watch --progress -``` - -### Not Enough Watchers - -Verify that you have enough available watchers in your system. If this value is too low, the file watcher in Webpack won't recognize the changes: - -```bash -cat /proc/sys/fs/inotify/max_user_watches -``` - -Arch users, add `fs.inotify.max_user_watches=524288` to `/etc/sysctl.d/99-sysctl.conf` and then execute `sysctl --system`. Ubuntu users (and possibly others), execute: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`. - -### macOS fsevents Bug - -On macOS, folders can get corrupted in certain scenarios. See [this article](https://github.com/livereload/livereload-site/blob/master/livereload.com/_articles/troubleshooting/os-x-fsevents-bug-may-prevent-monitoring-of-certain-folders.md). - -### Windows Paths - -Because webpack expects absolute paths for many config options such as `__dirname + "/app/folder"` the Windows `\` path separator can break some functionality. - -Use the correct separators. I.e. `path.resolve(__dirname, "app/folder")` or `path.join(__dirname, "app", "folder")`. - -### Vim - -On some machines Vim is preconfigured with the [backupcopy option](http://vimdoc.sourceforge.net/htmldoc/options.html#'backupcopy') set to `auto`. This could potentially cause problems with the system's file watching mechanism. Switching this option to `yes` will make sure a copy of the file is made and the original one overwritten on save. - -`:set backupcopy=yes` - -### Saving in WebStorm - -When using the JetBrains WebStorm IDE, you may find that saving changed files does not trigger the watcher as you might expect. Try disabling the `safe write` option in the settings, which determines whether files are saved to a temporary location first before the originals are overwritten: uncheck `File > Settings... > System Settings > Use "safe write" (save changes to a temporary file first)`. - - -# Externals - -The `externals` configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment. This feature is typically most useful to __library developers__, however there are a variety of applications for it. - -T> __consumer__ here is any end user application that includes the library that you have bundled using webpack. - - -## `externals` - -`string` `object` `function` `regex` - -__Prevent bundling__ of certain `import`ed packages and instead retrieve these _external dependencies_ at runtime. - -For example, to include [jQuery](https://jquery.com/) from a CDN instead of bundling it: - -__index.html__ - -``` html -<script - src="https://code.jquery.com/jquery-3.1.0.js" - integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" - crossorigin="anonymous"> -</script> -``` - -__webpack.config.js__ - -```javascript -module.exports = { - //... - externals: { - jquery: 'jQuery' - } -}; -``` - -This leaves any dependent modules unchanged, i.e. the code shown below will still work: - -```javascript -import $ from 'jquery'; - -$('.my-element').animate(/* ... */); -``` - -The bundle with external dependencies can be used in various module contexts, such as [CommonJS, AMD, global and ES2015 modules](/concepts/modules). The external library may be available in any of these forms: - -- __root__: The library should be available as a global variable (e.g. via a script tag). -- __commonjs__: The library should be available as a CommonJS module. -- __commonjs2__: Similar to the above but where the export is `module.exports.default`. -- __amd__: Similar to `commonjs` but using AMD module system. - -The following syntaxes are accepted... - - -### string - -See the example above. The property name `jquery` indicates that the module `jquery` in `import $ from 'jquery'` should be excluded. In order to replace this module, the value `jQuery` will be used to retrieve a global `jQuery` variable. In other words, when a string is provided it will be treated as `root` (defined above and below). - - -### array - -```javascript -module.exports = { - //... - externals: { - subtract: ['./math', 'subtract'] - } -}; -``` - -`subtract: ['./math', 'subtract']` converts to a parent child construct, where `./math` is the parent module and your bundle only requires the subset under `subtract` variable. - - -### object - -W> An object with `{ root, amd, commonjs, ... }` is only allowed for [`libraryTarget: 'umd'`](/configuration/output/#output-librarytarget). It's not allowed for other library targets. - -```javascript -module.exports = { - //... - externals : { - react: 'react' - }, - - // or - - externals : { - lodash : { - commonjs: 'lodash', - amd: 'lodash', - root: '_' // indicates global variable - } - }, - - // or - - externals : { - subtract : { - root: ['math', 'subtract'] - } - } -}; -``` - -This syntax is used to describe all the possible ways that an external library can be available. `lodash` here is available as `lodash` under AMD and CommonJS module systems but available as `_` in a global variable form. `subtract` here is available via the property `subtract` under the global `math` object (e.g. `window['math']['subtract']`). - - -### function - -It might be useful to define your own function to control the behavior of what you want to externalize from webpack. [webpack-node-externals](https://www.npmjs.com/package/webpack-node-externals), for example, excludes all modules from the `node_modules` directory and provides some options to, for example, whitelist packages. - -It basically comes down to this: - -```javascript -module.exports = { - //... - externals: [ - function(context, request, callback) { - if (/^yourregex$/.test(request)){ - return callback(null, 'commonjs ' + request); - } - callback(); - } - ] -}; -``` - -The `'commonjs ' + request` defines the type of module that needs to be externalized. - - -### regex - -Every dependency that matches the given regular expression will be excluded from the output bundles. - -```javascript -module.exports = { - //... - externals: /^(jquery|\$)$/i -}; -``` - -In this case any dependency named `jQuery`, capitalized or not, or `$` would be externalized. - -### Combining syntaxes - -Sometimes you may want to use a combination of the above syntaxes. This can be done in the following manner: - -```javascript -module.exports = { - //... - externals: [ - { - // String - react: 'react', - // Object - lodash : { - commonjs: 'lodash', - amd: 'lodash', - root: '_' // indicates global variable - }, - // Array - subtract: ['./math', 'subtract'] - }, - // Function - function(context, request, callback) { - if (/^yourregex$/.test(request)){ - return callback(null, 'commonjs ' + request); - } - callback(); - }, - // Regex - /^(jquery|\$)$/i - ] -}; -``` - -For more information on how to use this configuration, please refer to the article on [how to author a library](/guides/author-libraries). - - -# Node - -These options configure whether to polyfill or mock certain [Node.js globals](https://nodejs.org/docs/latest/api/globals.html) and modules. This allows code originally written for the Node.js environment to run in other environments like the browser. - -This feature is provided by webpack's internal [`NodeStuffPlugin`](https://github.com/webpack/webpack/blob/master/lib/NodeStuffPlugin.js) plugin. If the target is "web" (default) or "webworker", the [`NodeSourcePlugin`](https://github.com/webpack/webpack/blob/master/lib/node/NodeSourcePlugin.js) plugin is also activated. - - -## `node` - -`object` - -This is an object where each property is the name of a Node global or module and each value may be one of the following... - -- `true`: Provide a polyfill. -- `"mock"`: Provide a mock that implements the expected interface but has little or no functionality. -- `"empty"`: Provide an empty object. -- `false`: Provide nothing. Code that expects this object may crash with a `ReferenceError`. Code that attempts to import the module using `require('modulename')` may trigger a `Cannot find module "modulename"` error. - -W> Not every Node global supports all four options. The compiler will throw an error for property-value combinations that aren't supported (e.g. `process: 'empty'`). See the sections below for more details. - -These are the defaults: - -```js -module.exports = { - //... - node: { - console: false, - global: true, - process: true, - __filename: 'mock', - __dirname: 'mock', - Buffer: true, - setImmediate: true - - // See "Other node core libraries" for additional options. - } -}; -``` - -Since webpack 3.0.0, the `node` option may be set to `false` to completely turn off the `NodeStuffPlugin` and `NodeSourcePlugin` plugins. - - -## `node.console` - -`boolean | "mock"` - -Default: `false` - -The browser provides a `console` object with a very similar interface to the Node.js `console`, so a polyfill is generally not needed. - - -## `node.process` - -`boolean | "mock"` - -Default: `true` - - -## `node.global` - -`boolean` - -Default: `true` - -See [the source](https://github.com/webpack/webpack/blob/master/buildin/global.js) for the exact behavior of this object. - - -## `node.__filename` - -`boolean | "mock"` - -Default: `"mock"` - -Options: - -- `true`: The filename of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). -- `false`: The regular Node.js `__filename` behavior. The filename of the __output__ file when run in a Node.js environment. -- `"mock"`: The fixed value `"index.js"`. - - -## `node.__dirname` - -`boolean | "mock"` - -Default: `"mock"` - -Options: - -- `true`: The dirname of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). -- `false`: The regular Node.js `__dirname` behavior. The dirname of the __output__ file when run in a Node.js environment. -- `"mock"`: The fixed value `"/"`. - - -## `node.Buffer` - -`boolean | "mock"` - -Default: `true` - - -## `node.setImmediate` - -`boolean | "mock" | "empty"` - -Default: `true` - - -## Other node core libraries - -`boolean | "mock" | "empty"` - -W> This option is only activated (via `NodeSourcePlugin`) when the target is unspecified, "web" or "webworker". - -Polyfills for Node.js core libraries from [`node-libs-browser`](https://github.com/webpack/node-libs-browser) are used if available, when the `NodeSourcePlugin` plugin is enabled. See the list of [Node.js core libraries and their polyfills](https://github.com/webpack/node-libs-browser#readme). - -By default, webpack will polyfill each library if there is a known polyfill or do nothing if there is not one. In the latter case, webpack will behave as if the module name was configured with the `false` value. - -T> To import a built-in module, use [`__non_webpack_require__`](/api/module-variables/#__non_webpack_require__-webpack-specific-), i.e. `__non_webpack_require__('modulename')` instead of `require('modulename')`. - -Example: - -```js -module.exports = { - //... - node: { - dns: 'mock', - fs: 'empty', - path: true, - url: false - } -}; -``` - - -# Performance - -These options allows you to control how webpack notifies you of assets and entry points that exceed a specific file limit. -This feature was inspired by the idea of [webpack Performance Budgets](https://github.com/webpack/webpack/issues/3216). - -## `performance` - -`object` - -Configure how performance hints are shown. For example if you have an asset that is over 250kb, webpack will emit a warning notifying you of this. - - -## `performance.hints` - -`false | "error" | "warning"` - -Turns hints on/off. In addition, tells webpack to throw either an error or a warning when hints are found. This property is set to `"warning"` by default. - -Given an asset is created that is over 250kb: - -```js -module.exports = { - //... - performance: { - hints: false - } -}; -``` - -No hint warnings or errors are shown. - -```js -module.exports = { - //... - performance: { - hints: 'warning' - } -}; -``` - -A warning will be displayed notifying you of a large asset. We recommend something like this for development environments. - -```js -module.exports = { - //... - performance: { - hints: 'error' - } -}; -``` - -An error will be displayed notifying you of a large asset. We recommend using `hints: "error"` during production builds to help prevent deploying production bundles that are too large, impacting webpage performance. - -## `performance.maxEntrypointSize` - -`int` - -An entry point represents all assets that would be utilized during initial load time for a specific entry. This option controls when webpack should emit performance hints based on the maximum entry point size. The default value is `250000` (bytes). - -```js -module.exports = { - //... - performance: { - maxEntrypointSize: 400000 - } -}; -``` - -## `performance.maxAssetSize` - -`int` - -An asset is any emitted file from webpack. This option controls when webpack emits a performance hint based on individual asset size. The default value is `250000` (bytes). - - -```js -module.exports = { - //... - performance: { - maxAssetSize: 100000 - } -}; -``` - -## `performance.assetFilter` - -`Function` - -This property allows webpack to control what files are used to calculate performance hints. The default function is seen below: - -```js -function assetFilter(assetFilename) { - return !(/\.map$/.test(assetFilename)); -} -``` - -You can override this property by passing your own function in: - -```js -module.exports = { - //... - performance: { - assetFilter: function(assetFilename) { - return assetFilename.endsWith('.js'); - } - } -}; -``` - -The example above will only give you performance hints based on `.js` files. - - -# Stats - -The `stats` option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you don't want to use `quiet` or `noInfo` because you want some bundle information, but not all of it. - -T> For webpack-dev-server, this property needs to be in the `devServer` object. - -W> This option does not have any effect when using the Node.js API. - -## `stats` - -`object` `string` - -There are some presets available to use as a shortcut. Use them like this: - -```js -module.exports = { - //... - stats: 'errors-only' -}; -``` - -| Preset | Alternative | Description | -|--------|-------------|-------------| -| `"errors-only"` | _none_ | Only output when errors happen | -| `"minimal"` | _none_ | Only output when errors or new compilation happen | -| `"none"` | `false` | Output nothing | -| `"normal"` | `true` | Standard output | -| `"verbose"` | _none_ | Output everything | - -For more granular control, it is possible to specify exactly what information you want. Please note that all of the options in this object are optional. - -<!-- eslint-skip --> - -```js -module.exports = { - //... - stats: { - // fallback value for stats options when an option is not defined (has precedence over local webpack defaults) - all: undefined, - - // Add asset Information - assets: true, - - // Sort assets by a field - // You can reverse the sort with `!field`. - // Some possible values: 'id' (default), 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - assetsSort: "field", - - // Add build date and time information - builtAt: true, - - // Add information about cached (not built) modules - cached: true, - - // Show cached assets (setting this to `false` only shows emitted files) - cachedAssets: true, - - // Add children information - children: true, - - // Add chunk information (setting this to `false` allows for a less verbose output) - chunks: true, - - // Add namedChunkGroups information - chunkGroups: true, - - // Add built modules information to chunk information - chunkModules: true, - - // Add the origins of chunks and chunk merging info - chunkOrigins: true, - - // Sort the chunks by a field - // You can reverse the sort with `!field`. Default is `id`. - // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - chunksSort: "field", - - // Context directory for request shortening - context: "../src/", - - // `webpack --colors` equivalent - colors: false, - - // Display the distance from the entry point for each module - depth: false, - - // Display the entry points with the corresponding bundles - entrypoints: false, - - // Add --env information - env: false, - - // Add errors - errors: true, - - // Add details to errors (like resolving log) - errorDetails: true, - - // Exclude assets from being displayed in stats - // This can be done with a String, a RegExp, a Function getting the assets name - // and returning a boolean or an Array of the above. - excludeAssets: "filter" | /filter/ | (assetName) => true | false | - ["filter"] | [/filter/] | [(assetName) => true|false], - - // Exclude modules from being displayed in stats - // This can be done with a String, a RegExp, a Function getting the modules source - // and returning a boolean or an Array of the above. - excludeModules: "filter" | /filter/ | (moduleSource) => true | false | - ["filter"] | [/filter/] | [(moduleSource) => true|false], - - // See excludeModules - exclude: "filter" | /filter/ | (moduleSource) => true | false | - ["filter"] | [/filter/] | [(moduleSource) => true|false], - - // Add the hash of the compilation - hash: true, - - // Set the maximum number of modules to be shown - maxModules: 15, - - // Add built modules information - modules: true, - - // Sort the modules by a field - // You can reverse the sort with `!field`. Default is `id`. - // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - modulesSort: "field", - - // Show dependencies and origin of warnings/errors (since webpack 2.5.0) - moduleTrace: true, - - // Show performance hint when file size exceeds `performance.maxAssetSize` - performance: true, - - // Show the exports of the modules - providedExports: false, - - // Add public path information - publicPath: true, - - // Add information about the reasons why modules are included - reasons: true, - - // Add the source code of modules - source: false, - - // Add timing information - timings: true, - - // Show which exports of a module are used - usedExports: false, - - // Add webpack version information - version: true, - - // Add warnings - warnings: true, - - // Filter warnings to be shown (since webpack 2.4.0), - // can be a String, Regexp, a function getting the warning and returning a boolean - // or an Array of a combination of the above. First match wins. - warningsFilter: "filter" | /filter/ | ["filter", /filter/] | (warning) => true|false - } -} -``` - -If you want to use one of the pre-defined behaviours e.g. `'minimal'` but still override one or more of the rules, see [the source code](https://github.com/webpack/webpack/blob/master/lib/Stats.js#L1394-L1401). You would want to copy the configuration options from `case 'minimal': ...` and add your additional rules while providing an object to `stats`. - -__webpack.config.js__ - -```javascript -module.exports = { - //.. - stats: { - // copied from `'minimal'` - all: false, - modules: true, - maxModules: 0, - errors: true, - warnings: true, - // our additional options - moduleTrace: true, - errorDetails: true - } -}; -``` - -### Sorting fields - -For `assetsSort`, `chunksSort` and `moduleSort` there are several possible fields that you can sort items by: - -- `id` is the item's id; -- `name` - a item's name that was assigned to it upon importing; -- `size` - a size of item in bytes; -- `chunks` - what chunks the item originates from (for example, if there are multiple subchunks for one chunk - the subchunks will be grouped together according to their main chunk); -- `errors` - amount of errors in items; -- `warnings` - amount of warnings in items; -- `failed` - whether the item has failed compilation; -- `cacheable` - whether the item is cacheable; -- `built` - whether the asset has been built; -- `prefetched` - whether the asset will be prefetched; -- `optional` - whether the asset is optional; -- `identifier` - identifier of the item; -- `index` - item's processing index; -- `index2` -- `profile` -- `issuer` - an identifier of the issuer; -- `issuerId` - an id of the issuer; -- `issuerName` - a name of the issuer; -- `issuerPath` - a full issuer object. There's no real need to sort by this field; - - -# Other Options - - -These are the remaining configuration options supported by webpack. - -W> Help Wanted: This page is still a work in progress. If you are familiar with any of the options for which the description or examples are incomplete, please create an issue and submit a PR at the [docs repo](https://github.com/webpack/webpack.js.org)! - - -## `amd` - -`object` - -Set the value of `require.amd` or `define.amd`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - amd: { - jQuery: true - } -}; -``` - -Certain popular modules written for AMD, most notably jQuery versions 1.7.0 to 1.9.1, will only register as an AMD module if the loader indicates it has taken [special allowances](https://github.com/amdjs/amdjs-api/wiki/jQuery-and-AMD) for multiple versions being included on a page. - -The allowances were the ability to restrict registrations to a specific version or to support different sandboxes with different defined modules. - -This option allows you to set the key your module looks for to a truthy value. -As it happens, the AMD support in webpack ignores the defined name anyways. - - -## `bail` - -`boolean` - -Fail out on the first error instead of tolerating it. By default webpack will log these errors in red in the terminal, as well as the browser console when using HMR, but continue bundling. To enable it: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - bail: true -}; -``` - -This will force webpack to exit its bundling process. - - -## `cache` - -`boolean` `object` - -Cache the generated webpack modules and chunks to improve build speed. Caching is enabled by default while in watch mode. To disable caching simply pass: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - cache: false -}; -``` - -If an object is passed, webpack will use this object for caching. Keeping a reference to this object will allow one to share the same cache between compiler calls: - -__webpack.config.js__ - -```javascript -let SharedCache = {}; - -module.exports = { - //... - cache: SharedCache -}; -``` - -W> Don't share the cache between calls with different options. - -?> Elaborate on the warning and example - calls with different configuration options? - - -## `loader` - -`object` - -Expose custom values into the loader context. - -?> Add an example... - - -## `parallelism` - -`number` - -Limit the number of parallel processed modules. Can be used to fine tune performance or to get more reliable profiling results. - - -## `profile` - -`boolean` - -Capture a "profile" of the application, including statistics and hints, which can then be dissected using the [Analyze](https://webpack.github.io/analyse/) tool. - -T> Use the [StatsPlugin](https://www.npmjs.com/package/stats-webpack-plugin) for more control over the generated profile. - -T> Combine with `parallelism: 1` for better results. - - -## `recordsPath` - -`string` - -Use this option to generate a JSON file containing webpack "records" -- pieces of data used to store module identifiers across multiple builds. You can use this file to track how modules change between builds. To generate one, simply specify a location: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - recordsPath: path.join(__dirname, 'records.json') -}; -``` - -Records are particularly useful if you have a complex setup that leverages [Code Splitting](/guides/code-splitting). The data can be used to ensure the split bundles are achieving the [caching](/guides/caching) behavior you need. - -T> Note that although this file is generated by the compiler, you may still want to track it in source control to keep a history of how it has changed over time. - -W> Setting `recordsPath` will essentially set `recordsInputPath` and `recordsOutputPath` to the same location. This is usually all that's necessary unless you decide to change the name of the file containing the records. See below for an example. - - -## `recordsInputPath` - -`string` - -Specify the file from which to read the last set of records. This can be used to rename a records file. See the example below. - - -## `recordsOutputPath` - -`string` - -Specify where the records should be written. The following example shows how you might use this option in combination with `recordsInputPath` to rename a records file: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - recordsInputPath: path.join(__dirname, 'records.json'), - recordsOutputPath: path.join(__dirname, 'newRecords.json') -}; -``` - - -## `name` - -`string` - -Name of the configuration. Used when loading multiple configurations. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - name: 'admin-app' -}; -``` diff --git a/src/content/contribute/_contribute_all.md b/src/content/contribute/_contribute_all.md deleted file mode 100644 index beab316a12a7..000000000000 --- a/src/content/contribute/_contribute_all.md +++ /dev/null @@ -1,979 +0,0 @@ - - -# Contribute - -The people who contribute to webpack do so for the love of open source, our users and ecosystem, and most importantly, pushing the web forward together. Because of our [Open Collective](https://opencollective.com/webpack) model for funding and transparency, we are able to funnel support and funds through contributors, dependent projects, and the contributor and core teams. To make a donation, simply click the button below... - -<div align="center"> - <a href="https://opencollective.com/webpack/donate" target="_blank"> - <img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" width=300 /> - </a> -</div> - -But what is the return on the investment? - - -## Developers - -The biggest core feature we'd like to provide is enjoyable development experience. Developers like you can help by contributing to rich and vibrant documentation, issuing pull requests to help us cover niche use cases, and to help sustain what you love about webpack. - -### How Can I Help? - -Anybody can help by doing any of the following: - -- Ask your employer to use webpack in projects. -- Help us write and maintain the content on this site (see the [writer's guide](/writers-guide)). -- Contribute to the [core repository](https://github.com/webpack/webpack). -- Become a backer or sponsor on [open collective](https://opencollective.com/webpack#support). - -### Encouraging Employers - -You can ask your employer to improve your workflow by leveraging webpack: an all-in-one tool for fonts, images and image optimization, and json. Explain to them how webpack will attempt to bundle your code and assets the best it can for the smallest file size, leading to speedier sites and applications. - -### Your Contributions - -Contributing to webpack is not contributing to an exclusive club. You as a developer are contributing to the overall health of downstream projects. Hundreds, if not thousands, of projects depend on webpack and contributing will make the ecosystem better for all users. - -The remainder of this section of the site is dedicated to developers such as yourself who would like to become a part of our ever-growing community: - -- [Writing a Loader](./writing-a-loader) -- [Writing a Plugin](./writing-a-plugin) -- [Plugin Patterns](./plugin-patterns) -- [Release Process](./release-process) - - -## Executives - -CTO's, VPs, and owners can help too! - -<!-- add slides here regarding monetary value/dev time/tooling --> - -webpack is an all-in-one tool for bundling your code. It can handle fonts, images, data and more with the help of community-driven plugins and loaders. Having all of your assets be handled by one tool is immensely helpful, as you or your team can spend less time making sure a machine with many moving parts is working correctly and more time building your product. - -### Sponsorship - -Aside from monetary assistance, companies can support webpack by: - -- Providing developers that are not actively working on a project. -- Contributing computing power for improved CI and regression testing. - -You can also encourage your developers to contribute to the ecosystem by open-sourcing webpack loaders, plugins and other utilities. And, as mentioned above, we would greatly appreciate any help increasing our CI/CD infrastructure. - -### Anyone Else - -To anyone else who is interested in helping our mission -- e.g. venture capitalists, government entities, digital agencies, etc. -- we would love for you to work with us, one of the top npm packages, to improve your product! Please don't hesitate to reach out with questions. - -<!-- add slides here --> - - -# Writer's Guide - -The following sections contain all you need to know about editing and formatting the content within this site. Make sure to do some research before starting your edits or additions. Sometimes the toughest part is finding where the content should live and determining whether or not it already exists. - - -## Process - -1. Check related issue if an article links to one. -2. Hit `edit` and expand on the structure. -3. PR changes. - - -## YAML Frontmatter - -Each article contains a small section at the top written in [YAML Frontmatter](https://jekyllrb.com/docs/frontmatter/): - -``` yaml ---- -title: My Article -group: My Sub-Section -sort: 3 -contributors: - - [github username] -related: - - title: Title of Related Article - url: [url of related article] ---- -``` - -Let's break these down: - -- `title`: The name of the article. -- `group`: The name of the sub-section -- `sort`: The order of the article within its section (or) sub-section if it is present. -- `contributors`: A list of GitHub usernames who have contributed to this article. -- `related`: Any related reading or useful examples. - -Note that `related` will generate a __Further Reading__ section at the bottom of the page and `contributors` will yield a __Contributors__ section below it. If you edit an article and would like recognition, don't hesitate to add your GitHub username to the `contributors` list. - - -## Article Structure - -1. Brief Introduction - a paragraph or two so you get the basic idea about the what and why. -2. Outline Remaining Content – how the content will be presented. -3. Main Content - tell what you promised to tell. -4. Conclusion - tell what you told and recap the main points. - - -## Typesetting - -- webpack should always be written in lower-case letters. Even at the beginning of a sentence. ([source](https://github.com/webpack/media#name)) -- loaders are enclosed in backticks and [kebab-cased](https://en.wikipedia.org/w/index.php?title=Kebab_case): `css-loader`, `ts-loader`, … -- plugins are enclosed in backticks and [camel-cased](https://en.wikipedia.org/wiki/Camel_case): `BannerPlugin`, `NpmInstallWebpackPlugin`, … -- Use "webpack 2" to refer to a specific webpack version (~~"webpack v2"~~) -- Use ES5; ES2015, ES2016, … to refer to the ECMAScript standards (~~ES6~~, ~~ES7~~) - - -## Formatting - -### Code - -__Syntax: \`\`\`javascript … \`\`\`__ - -```javascript -function foo () { - return 'bar'; -} - -foo(); -``` - -### Lists - -- Boo -- Foo -- Zoo - -Lists should be ordered alphabetically. - -### Tables - -Parameter | Explanation | Input Type | Default Value ------------ | ------------------------------------------------ | ---------- |-------------- ---debug | Switch loaders to debug mode | boolean | false ---devtool | Define source map type for the bundled resources | string | - ---progress | Print compilation progress in percentage | boolean | false - -Tables should also be ordered alphabetically. - -### Configuration Properties - -The [configuration](/configuration) properties should be ordered alphabetically as well: - -- `devServer.compress` -- `devServer.contentBase` -- `devServer.hot` - -### Quotes - -#### Blockquote - -__Syntax: \>__ - -> This is a blockquote. - -#### Tip - -__Syntax: T\>__ - -T> This is a tip. - -__Syntax: W\>__ - -W> This is a warning. - -__Syntax: ?\>__ - -?> This is a todo. - - -# Writing a Loader - -A loader is a node module that exports a function. This function is called when a resource should be transformed by this loader. The given function will have access to the [Loader API](/api/loaders/) using the `this` context provided to it. - - -## Setup - -Before we dig into the different types of loaders, their usage, and examples, let's take a look at the three ways you can develop and test a loader locally. - -To test a single loader, you can simply use `path` to `resolve` a local file within a rule object: - -__webpack.config.js__ - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - use: [ - { - loader: path.resolve('path/to/loader.js'), - options: {/* ... */} - } - ] - } - ] - } -}; -``` - -To test multiple, you can utilize the `resolveLoader.modules` configuration to update where webpack will search for loaders. For example, if you had a local `/loaders` directory in your project: - -__webpack.config.js__ - -```js -module.exports = { - //... - resolveLoader: { - modules: [ - 'node_modules', - path.resolve(__dirname, 'loaders') - ] - } -}; -``` - -Last but not least, if you've already created a separate repository and package for your loader, you could [`npm link`](https://docs.npmjs.com/cli/link) it to the project in which you'd like to test it out. - - -## Simple Usage - -When a single loader is applied to the resource, the loader is called with only one parameter -- a string containing the content of the resource file. - -Synchronous loaders can simply `return` a single value representing the transformed module. In more complex cases, the loader can return any number of values by using the `this.callback(err, values...)` function. Errors are either passed to the `this.callback` function or thrown in a sync loader. - -The loader is expected to give back one or two values. The first value is a resulting JavaScript code as string or buffer. The second optional value is a SourceMap as JavaScript object. - - -## Complex Usage - -When multiple loaders are chained, it is important to remember that they are executed in reverse order -- either right to left or bottom to top depending on array format. - -- The last loader, called first, will be passed the contents of the raw resource. -- The first loader, called last, is expected to return JavaScript and an optional source map. -- The loaders in between will be executed with the result(s) of the previous loader in the chain. - -So, in the following example, the `foo-loader` would be passed the raw resource and the `bar-loader` would receive the output of the `foo-loader` and return the final transformed module and a source map if necessary. - -__webpack.config.js__ - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js/, - use: [ - 'bar-loader', - 'foo-loader' - ] - } - ] - } -}; -``` - - -## Guidelines - -The following guidelines should be followed when writing a loader. They are ordered in terms of importance and some only apply in certain scenarios, read the detailed sections that follow for more information. - -- Keep them __simple__. -- Utilize __chaining__. -- Emit __modular__ output. -- Make sure they're __stateless__. -- Employ __loader utilities__. -- Mark __loader dependencies__. -- Resolve __module dependencies__. -- Extract __common code__. -- Avoid __absolute paths__. -- Use __peer dependencies__. - -### Simple - -Loaders should do only a single task. This not only makes the job of maintaining each loader easier, but also allows them to be chained for usage in more scenarios. - -### Chaining - -Take advantage of the fact that loaders can be chained together. Instead of writing a single loader that tackles five tasks, write five simpler loaders that divide this effort. Isolating them not only keeps each individual loader simple, but may allow for them to be used for something you hadn't thought of originally. - -Take the case of rendering a template file with data specified via loader options or query parameters. It could be written as a single loader that compiles the template from source, executes it and returns a module that exports a string containing the HTML code. However, in accordance with guidelines, a simple `apply-loader` exists that can be chained with other open source loaders: - -- `jade-loader`: Convert template to a module that exports a function. -- `apply-loader`: Executes the function with loader options and returns raw HTML. -- `html-loader`: Accepts HTML and outputs a valid JavaScript module. - -T> The fact that loaders can be chained also means they don't necessarily have to output JavaScript. As long as the next loader in the chain can handle its output, the loader can return any type of module. - -### Modular - -Keep the output modular. Loader generated modules should respect the same design principles as normal modules. - -### Stateless - -Make sure the loader does not retain state between module transformations. Each run should always be independent of other compiled modules as well as previous compilations of the same module. - -### Loader Utilities - -Take advantage of the [`loader-utils`](https://github.com/webpack/loader-utils) package. It provides a variety of useful tools but one of the most common is retrieving the options passed to the loader. Along with `loader-utils`, the [`schema-utils`](https://github.com/webpack-contrib/schema-utils) package should be used for consistent JSON Schema based validation of loader options. Here's a brief example that utilizes both: - -__loader.js__ - -```js -import { getOptions } from 'loader-utils'; -import validateOptions from 'schema-utils'; - -const schema = { - type: 'object', - properties: { - test: { - type: 'string' - } - } -}; - -export default function(source) { - const options = getOptions(this); - - validateOptions(schema, options, 'Example Loader'); - - // Apply some transformations to the source... - - return `export default ${ JSON.stringify(source) }`; -} -``` - -### Loader Dependencies - -If a loader uses external resources (i.e. by reading from filesystem), they __must__ indicate it. This information is used to invalidate cacheable loaders and recompile in watch mode. Here's a brief example of how to accomplish this using the `addDependency` method: - -__loader.js__ - -```js -import path from 'path'; - -export default function(source) { - var callback = this.async(); - var headerPath = path.resolve('header.js'); - - this.addDependency(headerPath); - - fs.readFile(headerPath, 'utf-8', function(err, header) { - if(err) return callback(err); - callback(null, header + '\n' + source); - }); -} -``` - -### Module Dependencies - -Depending on the type of module, there may be a different schema used to specify dependencies. In CSS for example, the `@import` and `url(...)` statements are used. These dependencies should be resolved by the module system. - -This can be done in one of two ways: - -- By transforming them to `require` statements. -- Using the `this.resolve` function to resolve the path. - -The `css-loader` is a good example of the first approach. It transforms dependencies to `require`s, by replacing `@import` statements with a `require` to the other stylesheet and `url(...)` with a `require` to the referenced file. - -In the case of the `less-loader`, it cannot transform each `@import` to a `require` because all `.less` files must be compiled in one pass for variables and mixin tracking. Therefore, the `less-loader` extends the less compiler with custom path resolving logic. It then takes advantage of the second approach, `this.resolve`, to resolve the dependency through webpack. - -T> If the language only accepts relative urls (e.g. `url(file)` always refers to `./file`), you can use the `~` convention to specify references to installed modules (e.g. those in `node_modules`). So, in the case of `url`, that would look something like `url('~some-library/image.jpg')`. - -### Common Code - -Avoid generating common code in every module the loader processes. Instead, create a runtime file in the loader and generate a `require` to that shared module. - -### Absolute Paths - -Don't insert absolute paths into the module code as they break hashing when the root for the project is moved. There's a [`stringifyRequest`](https://github.com/webpack/loader-utils#stringifyrequest) method in `loader-utils` which can be used to convert an absolute path to a relative one. - -### Peer Dependencies - -If the loader you're working on is a simple wrapper around another package, then you should include the package as a `peerDependency`. This approach allows the application's developer to specify the exact version in the `package.json` if desired. - -For instance, the `sass-loader` [specifies `node-sass`](https://github.com/webpack-contrib/sass-loader/blob/master/package.json) as peer dependency like so: - -```json -{ - "peerDependencies": { - "node-sass": "^4.0.0" - } -} -``` - - -## Testing - -So you've written a loader, followed the guidelines above, and have it set up to run locally. What's next? Let's go through a simple unit testing example to ensure our loader is working the way we expect. We'll be using the [Jest](https://facebook.github.io/jest/) framework to do this. We'll also install `babel-jest` and some presets that will allow us to use the `import` / `export` and `async` / `await`. Let's start by installing and saving these as a `devDependencies`: - -``` bash -npm install --save-dev jest babel-jest babel-preset-env -``` - -__.babelrc__ - -```json -{ - "presets": [[ - "env", - { - "targets": { - "node": "4" - } - } - ]] -} -``` - -Our loader will process `.txt` files and simply replace any instance of `[name]` with the `name` option given to the loader. Then it will output a valid JavaScript module containing the text as it's default export: - -__src/loader.js__ - -```js -import { getOptions } from 'loader-utils'; - -export default function loader(source) { - const options = getOptions(this); - - source = source.replace(/\[name\]/g, options.name); - - return `export default ${ JSON.stringify(source) }`; -} -``` - -We'll use this loader to process the following file: - -__test/example.txt__ - -``` text -Hey [name]! -``` - -Pay close attention to this next step as we'll be using the [Node.js API](/api/node) and [`memory-fs`](https://github.com/webpack/memory-fs) to execute webpack. This lets us avoid emitting `output` to disk and will give us access to the `stats` data which we can use to grab our transformed module: - -``` bash -npm install --save-dev webpack memory-fs -``` - -__test/compiler.js__ - -```js -import path from 'path'; -import webpack from 'webpack'; -import memoryfs from 'memory-fs'; - -export default (fixture, options = {}) => { - const compiler = webpack({ - context: __dirname, - entry: `./${fixture}`, - output: { - path: path.resolve(__dirname), - filename: 'bundle.js', - }, - module: { - rules: [{ - test: /\.txt$/, - use: { - loader: path.resolve(__dirname, '../src/loader.js'), - options: { - name: 'Alice' - } - } - }] - } - }); - - compiler.outputFileSystem = new memoryfs(); - - return new Promise((resolve, reject) => { - compiler.run((err, stats) => { - if (err || stats.hasErrors()) reject(err); - - resolve(stats); - }); - }); -}; -``` - -T> In this case, we've inlined our webpack configuration but you can also accept a configuration as a parameter to the exported function. This would allow you to test multiple setups using the same compiler module. - -And now, finally, we can write our test and add an npm script to run it: - -__test/loader.test.js__ - -```js -import compiler from './compiler.js'; - -test('Inserts name and outputs JavaScript', async () => { - const stats = await compiler('example.txt'); - const output = stats.toJson().modules[0].source; - - expect(output).toBe('export default "Hey Alice!\\n"'); -}); -``` - -__package.json__ - -```json -{ - "scripts": { - "test": "jest" - } -} -``` - -With everything in place, we can run it and see if our new loader passes the test: - -``` bash - PASS test/loader.test.js - ✓ Inserts name and outputs JavaScript (229ms) - -Test Suites: 1 passed, 1 total -Tests: 1 passed, 1 total -Snapshots: 0 total -Time: 1.853s, estimated 2s -Ran all test suites. -``` - -It worked! At this point you should be ready to start developing, testing, and deploying your own loaders. We hope that you'll share your creations with the rest of the community! - - -# Writing a Plugin - -Plugins expose the full potential of the webpack engine to third-party developers. Using staged build callbacks, developers can introduce their own behaviors into the webpack build process. Building plugins is a bit more advanced than building loaders, because you'll need to understand some of the webpack low-level internals to hook into them. Be prepared to read some source code! - -## Creating a Plugin - -A plugin for webpack consists of - -- A named JavaScript function. -- Defines `apply` method in its prototype. -- Specifies an [event hook](/api/compiler-hooks/) to tap into. -- Manipulates webpack internal instance specific data. -- Invokes webpack provided callback after functionality is complete. - -```javascript -// A JavaScript class. -class MyExampleWebpackPlugin { - // Define `apply` as its prototype method which is supplied with compiler as its argument - apply(compiler) { - // Specify the event hook to attach to - compiler.hooks.emit.tapAsync( - 'MyExampleWebpackPlugin', - (compilation, callback) => { - console.log('This is an example plugin!'); - console.log('Here’s the `compilation` object which represents a single build of assets:', compilation); - - // Manipulate the build using the plugin API provided by webpack - compilation.addModule(/* ... */); - - callback(); - } - ); - } -} -``` - -## Basic plugin architecture - -Plugins are instantiated objects with an `apply` method on their prototype. This `apply` method is called once by the webpack compiler while installing the plugin. The `apply` method is given a reference to the underlying webpack compiler, which grants access to compiler callbacks. A simple plugin is structured as follows: - -```javascript -class HelloWorldPlugin { - apply(compiler) { - compiler.hooks.done.tap('Hello World Plugin', ( - stats /* stats is passed as argument when done hook is tapped. */ - ) => { - console.log('Hello World!'); - }); - } -} - -module.exports = HelloWorldPlugin; -``` - -Then to use the plugin, include an instance in your webpack config `plugins` array: - -```javascript -// webpack.config.js -var HelloWorldPlugin = require('hello-world'); - -module.exports = { - // ... config settings here ... - plugins: [new HelloWorldPlugin({ options: true })] -}; -``` - -## Compiler and Compilation - -Among the two most important resources while developing plugins are the `compiler` and `compilation` objects. Understanding their roles is an important first step in extending the webpack engine. - -```javascript -class HelloCompilationPlugin { - apply(compiler) { - // Tap into compilation hook which gives compilation as argument to the callback function - compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => { - // Now we can tap into various hooks available through compilation - compilation.hooks.optimize.tap('HelloCompilationPlugin', () => { - console.log('Assets are being optimized.'); - }); - }); - } -} - -module.exports = HelloCompilationPlugin; -``` - -The list of hooks available on the `compiler`, `compilation`, and other important objects, see the [plugins API](/api/plugins/) docs. - -## Async event hooks - -Some plugin hooks are asynchronous. To tap into them, we can use `tap` method which will behave in synchronous manner or use one of `tapAsync` method or `tapPromise` method which are asynchronous methods. - -### tapAsync - -When we use `tapAsync` method to tap into plugins, we need to call the callback function which is supplied as the last argument to our function. - -```javascript -class HelloAsyncPlugin { - apply(compiler) { - compiler.hooks.emit.tapAsync('HelloAsyncPlugin', (compilation, callback) => { - // Do something async... - setTimeout(function() { - console.log('Done with async work...'); - callback(); - }, 1000); - }); - } -} - -module.exports = HelloAsyncPlugin; -``` - -#### tapPromise - -When we use `tapPromise` method to tap into plugins, we need to return a promise which resolves when our asynchronous task is completed. - -```javascript -class HelloAsyncPlugin { - apply(compiler) { - compiler.hooks.emit.tapPromise('HelloAsyncPlugin', compilation => { - // return a Promise that resolves when we are done... - return new Promise((resolve, reject) => { - setTimeout(function() { - console.log('Done with async work...'); - resolve(); - }, 1000); - }); - }); - } -} - -module.exports = HelloAsyncPlugin; -``` - -## Example - -Once we can latch onto the webpack compiler and each individual compilations, the possibilities become endless for what we can do with the engine itself. We can reformat existing files, create derivative files, or fabricate entirely new assets. - -Let's write a simple example plugin that generates a new build file called `filelist.md`; the contents of which will list all of the asset files in our build. This plugin might look something like this: - -```javascript -class FileListPlugin { - apply(compiler) { - // emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well - compiler.hooks.emit.tapAsync('FileListPlugin', (compilation, callback) => { - // Create a header string for the generated file: - var filelist = 'In this build:\n\n'; - - // Loop through all compiled assets, - // adding a new line item for each filename. - for (var filename in compilation.assets) { - filelist += '- ' + filename + '\n'; - } - - // Insert this list into the webpack build as a new file asset: - compilation.assets['filelist.md'] = { - source: function() { - return filelist; - }, - size: function() { - return filelist.length; - } - }; - - callback(); - }); - } -} - -module.exports = FileListPlugin; -``` - -## Different Plugin Shapes - -A plugin can be classified into types based on the event hooks it taps into. Every event hook is pre-defined as synchronous or asynchronous or waterfall or parallel hook and hook is called internally using call/callAsync method. The list of hooks that are supported or can be tapped into are generally specified in this.hooks property. - -For example:- - -```javascript -this.hooks = { - shouldEmit: new SyncBailHook(['compilation']) -}; -``` - -It represents that the only hook supported is `shouldEmit` which is a hook of `SyncBailHook` type and the only parameter which will be passed to any plugin that taps into `shouldEmit` hook is `compilation`. - -Various types of hooks supported are :- - -### Synchronous Hooks - -- __SyncHook__ - - - Defined as `new SyncHook([params])` - - Tapped into using `tap` method. - - Called using `call(...params)` method. - -- __Bail Hooks__ - - - Defined using `SyncBailHook[params]` - - Tapped into using `tap` method. - - Called using `call(...params)` method. - - In these type of hooks, each of the plugin callbacks will be invoked one after the other with the specific `args`. If any value is returned except undefined by any plugin, then that value is returned by hook and no further plugin callback is invoked. Many useful events like `optimizeChunks`, `optimizeChunkModules` are SyncBailHooks. - -- __Waterfall Hooks__ - - - Defined using `SyncWaterfallHook[params]` - - Tapped into using `tap` method. - - Called using `call( ... params)` method - - Here each of the plugins are called one after the other with the arguments from the return value of the previous plugin. The plugin must take the order of its execution into account. - It must accept arguments from the previous plugin that was executed. The value for the first plugin is `init`. Hence at least 1 param must be supplied for waterfall hooks. This pattern is used in the Tapable instances which are related to the webpack templates like `ModuleTemplate`, `ChunkTemplate` etc. - -### Asynchronous Hooks - -- __Async Series Hook__ - - - Defined using `AsyncSeriesHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - The plugin handler functions are called with all arguments and a callback function with the signature `(err?: Error) -> void`. The handler functions are called in order of registration. `callback` is called after all the handlers are called. - This is also a commonly used pattern for events like `emit`, `run`. - -- __Async waterfall__ The plugins will be applied asynchronously in the waterfall manner. - - - Defined using `AsyncWaterfallHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - The plugin handler functions are called with the current value and a callback function with the signature `(err: Error, nextValue: any) -> void.` When called `nextValue` is the current value for the next handler. The current value for the first handler is `init`. After all handlers are applied, callback is called with the last value. If any handler passes a value for `err`, the callback is called with this error and no more handlers are called. - This plugin pattern is expected for events like `before-resolve` and `after-resolve`. - -- __Async Series Bail__ - - - Defined using `AsyncSeriesBailHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - someMethod() { - // Call a hook: - this.hooks.compilation.call(); - -- __Async Parallel__ - - - Defined using `AsyncParallelHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - -- __Async Series Bail__ - - - Defined using `AsyncSeriesBailHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - -# Plugin Patterns - -Plugins grant unlimited opportunity to perform customizations within the webpack build system. This allows you to create custom asset types, perform unique build modifications, or even enhance the webpack runtime while using middleware. The following are some features of webpack that become useful while writing plugins. - -## Exploring assets, chunks, modules, and dependencies - -After a compilation is sealed, all structures within the compilation may be traversed. - -```javascript -class MyPlugin { - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - // Explore each chunk (build output): - compilation.chunks.forEach(chunk => { - // Explore each module within the chunk (built inputs): - chunk.modules.forEach(module => { - // Explore each source file path that was included into the module: - module.fileDependencies.forEach(filepath => { - // we've learned a lot about the source structure now... - }); - }); - - // Explore each asset filename generated by the chunk: - chunk.files.forEach(filename => { - // Get the asset source for each file generated by the chunk: - var source = compilation.assets[filename].source(); - }); - }); - - callback(); - }); - } -} -module.exports = MyPlugin; -``` - -- `compilation.modules`: An array of modules (built inputs) in the compilation. Each module manages the build of a raw file from your source library. -- `module.fileDependencies`: An array of source file paths included into a module. This includes the source JavaScript file itself (ex: `index.js`), and all dependency asset files (stylesheets, images, etc) that it has required. Reviewing dependencies is useful for seeing what source files belong to a module. -- `compilation.chunks`: An array of chunks (build outputs) in the compilation. Each chunk manages the composition of a final rendered assets. -- `chunk.modules`: An array of modules that are included into a chunk. By extension, you may look through each module's dependencies to see what raw source files fed into a chunk. -- `chunk.files`: An array of output filenames generated by the chunk. You may access these asset sources from the `compilation.assets` table. - -### Monitoring the watch graph - -While running webpack middleware, each compilation includes a `fileDependencies` array (what files are being watched) and a `fileTimestamps` hash that maps watched file paths to a timestamp. These are extremely useful for detecting what files have changed within the compilation: - -```javascript -class MyPlugin { - constructor() { - this.startTime = Date.now(); - this.prevTimestamps = {}; - } - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - var changedFiles = Object.keys(compilation.fileTimestamps).filter( - watchfile => { - return ( - (this.prevTimestamps[watchfile] || this.startTime) < - (compilation.fileTimestamps[watchfile] || Infinity) - ); - } - ); - - this.prevTimestamps = compilation.fileTimestamps; - callback(); - }); - } -} - -module.exports = MyPlugin; -``` - -You may also feed new file paths into the watch graph to receive compilation triggers when those files change. Simply push valid file paths into the `compilation.fileDependencies` array to add them to the watch. Note: the `fileDependencies` array is rebuilt in each compilation, so your plugin must push its own watched dependencies into each compilation to keep them under watch. - -## Changed chunks - -Similar to the watch graph, it's fairly simple to monitor changed chunks (or modules, for that matter) within a compilation by tracking their hashes. - -```javascript -class MyPlugin { - constructor() { - this.chunkVersions = {}; - } - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - var changedChunks = compilation.chunks.filter(chunk => { - var oldVersion = this.chunkVersions[chunk.name]; - this.chunkVersions[chunk.name] = chunk.hash; - return chunk.hash !== oldVersion; - }); - callback(); - }); - } -} - -module.exports = MyPlugin; -``` - - -# Release Process - -The release process for deploying webpack is actually quite painless. Read through the following steps, so you have a clear understanding of how it's done. - - -## Pull Requests - -When merging pull requests into the `master` branch, select the _Create Merge Commit_ option. - - -## Releasing - -```sh -npm version patch && git push --follow-tags && npm publish -npm version minor && git push --follow-tags && npm publish -npm version major && git push --follow-tags && npm publish -``` - -_This will increment the package version, commits the changes, cuts a __local tag__, push to github & publish the npm package._ - -After that go to the github [releases page](https://github.com/webpack/webpack/releases) and write a Changelog for the new tag. - - -# Debugging - -When contributing to the core repo, writing a loader/plugin, or even just working on complex project, debugging tools can be central to your workflow. Whether the problem is slow performance on a large project or an unhelpful traceback, the following utilities can make figuring it out less painful. - -- The [`stats` data](/api/stats) made available through [Node](/api/node#stats-object) and the [CLI](/api/cli#common-options). -- Chrome __DevTools__ via `node-nightly` and the latest Node.js versions. - - -## Stats - -Whether you want to sift through [this data](/api/stats) manually or use a tool to process it, the `stats` data can be extremely useful when debugging build issues. We won't go in depth here as there's an [entire page](/api/stats) dedicated to its contents, but know that you can use it to find the following information: - -- The contents of every module. -- The modules contained within every chunk. -- Per module compilation and resolving stats. -- Build errors and warnings. -- The relationships between modules. -- And much more... - -On top of that, the official [analyze tool](https://github.com/webpack/analyse) and [various others](/guides/code-splitting#bundle-analysis) will accept this data and visualize it in various ways. - - -## DevTools - -While [`console`](https://nodejs.org/api/console.html) statements may work well in simpler scenarios, sometimes a more robust solution is needed. As most front-end developers already know, Chrome DevTools are a life saver when debugging web applications, _but they don’t have to stop there_. As of Node v6.3.0+, developers can use the built-in `--inspect` flag to debug a node program in DevTools. - -This gives you the power to easily create breakpoints, debug memory usage, expose and examine objects in the console, and much more. In this short demo, we'll utilize the [`node-nightly`](https://github.com/hemanth/node-nightly) package which provides access to the latest and greatest inspecting capabilities. - -W> The `--inspect` interface has been available since v6.3.0 so feel to try it out with your local version, but be warned that certain features and flags may differ from the ones in this demo. - -Let's start by installing it globally: - -``` bash -npm install --global node-nightly -``` - -Now, we'll need to run it once to finish the installation: - -``` bash -node-nightly -``` - -Now, we can simply use `node-nightly` along with the `--inspect` flag to start our build in any webpack-based project. Note that we cannot run NPM `scripts`, e.g. `npm run build`, so we'll have specify the full `node_modules` path: - -``` bash -node-nightly --inspect ./node_modules/webpack/bin/webpack.js -``` - -Which should output something like: - -``` bash -Debugger listening on ws://127.0.0.1:9229/c624201a-250f-416e-a018-300bbec7be2c -For help see https://nodejs.org/en/docs/inspector -``` - -Now jump to `chrome://inspect` in the browser and you should see any active scripts you've inspected under the _Remote Target_ header. Click the "inspect" link under each script to open a dedicated debugger or the _Open dedicated DevTools for Node_ link for a session that will connect automatically. You can also check out the [NiM extension](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj), a handy Chrome plugin that will automatically open a DevTools tab every time you `--inspect` a script. - -We recommend using the `--inspect-brk` flag which will break on the first statement of the script allowing you to go through the source to set breakpoints and start/stop the build as you please. Also, don't forget that you can still pass arguments to the script. For example, if you have multiple configuration files you could pass `--config webpack.prod.js` to specify the configuration you'd like to debug. diff --git a/src/content/guides/_guides_all.md b/src/content/guides/_guides_all.md deleted file mode 100644 index dab542340ea2..000000000000 --- a/src/content/guides/_guides_all.md +++ /dev/null @@ -1,4880 +0,0 @@ - - -# Installation - -This guide goes through the various methods used to install webpack. - - -## Prerequisites - -Before we begin, make sure you have a fresh version of [Node.js](https://nodejs.org/en/) installed. The current Long Term Support (LTS) release is an ideal starting point. You may run into a variety of issues with the older versions as they may be missing functionality webpack and/or its related packages require. - - -## Local Installation - -The latest webpack release is: - -[](https://github.com/webpack/webpack/releases) - -To install the latest release or a specific version, run one of the following commands: - -``` bash -npm install --save-dev webpack -npm install --save-dev webpack@<version> -``` - -If you're using webpack v4 or later, you'll need to install the [CLI](/api/cli/). - -``` bash -npm install --save-dev webpack-cli -``` - -Installing locally is what we recommend for most projects. This makes it easier to upgrade projects individually when breaking changes are introduced. Typically webpack is run via one or more [npm scripts](https://docs.npmjs.com/misc/scripts) which will look for a webpack installation in your local `node_modules` directory: - -```json -"scripts": { - "start": "webpack --config webpack.config.js" -} -``` - -T> To run the local installation of webpack you can access its bin version as `node_modules/.bin/webpack`. - - -## Global Installation - -The following NPM installation will make `webpack` available globally: - -``` bash -npm install --global webpack -``` - -W> Note that this is __not a recommended practice__. Installing globally locks you down to a specific version of webpack and could fail in projects that use a different version. - - -## Bleeding Edge - -If you are enthusiastic about using the latest that webpack has to offer, you can install beta versions or even directly from the webpack repository using the following commands: - -``` bash -npm install webpack@beta -npm install webpack/webpack#<tagname/branchname> -``` - -W> Take caution when installing these bleeding edge releases! They may still contain bugs and therefore should not be used in production. - - -# Getting Started - -Webpack is used to compile JavaScript modules. Once [installed](/guides/installation), you can interface with webpack either from its [CLI](/api/cli) or [API](/api/node). If you're still new to webpack, please read through the [core concepts](/concepts) and [this comparison](/comparison) to learn why you might use it over the other tools that are out in the community. - -## Basic Setup - -First let's create a directory, initialize npm, [install webpack locally](/guides/installation#local-installation), and install the webpack-cli (the tool used to run webpack on the command line): - -``` bash -mkdir webpack-demo && cd webpack-demo -npm init -y -npm install webpack webpack-cli --save-dev -``` - -T> Throughout the Guides we will use `diff` blocks to show you what changes we're making to directories, files, and code. - -Now we'll create the following directory structure, files and their contents: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- index.html -+ |- /src -+ |- index.js -``` - -__src/index.js__ - -``` javascript -function component() { - let element = document.createElement('div'); - - // Lodash, currently included via a script, is required for this line to work - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; -} - -document.body.appendChild(component()); -``` - -__index.html__ - -``` html -<!doctype html> -<html> - <head> - <title>Getting Started</title> - <script src="https://unpkg.com/lodash@4.16.6"></script> - </head> - <body> - <script src="./src/index.js"></script> - </body> -</html> -``` - -We also need to adjust our `package.json` file in order to make sure we mark our package as `private`, as well as removing the `main` entry. This is to prevent an accidental publish of your code. - -T> If you want to learn more about the inner workings of `package.json`, then we recommend reading the [npm documentation](https://docs.npmjs.com/files/package.json). - -__package.json__ - -``` diff - { - "name": "webpack-demo", - "version": "1.0.0", - "description": "", -+ "private": true, -- "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "webpack": "^4.20.2", - "webpack-cli": "^3.1.2" - }, - "dependencies": {} - } -``` - -In this example, there are implicit dependencies between the `<script>` tags. Our `index.js` file depends on `lodash` being included in the page before it runs. This is because `index.js` never explicitly declared a need for `lodash`; it just assumes that the global variable `_` exists. - -There are problems with managing JavaScript projects this way: - -- It is not immediately apparent that the script depends on an external library. -- If a dependency is missing, or included in the wrong order, the application will not function properly. -- If a dependency is included but not used, the browser will be forced to download unnecessary code. - -Let's use webpack to manage these scripts instead. - -## Creating a Bundle - -First we'll tweak our directory structure slightly, separating the "source" code (`/src`) from our "distribution" code (`/dist`). The "source" code is the code that we'll write and edit. The "distribution" code is the minimized and optimized `output` of our build process that will eventually be loaded in the browser: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- /dist -+ |- index.html -- |- index.html - |- /src - |- index.js -``` - -To bundle the `lodash` dependency with `index.js`, we'll need to install the library locally: - -``` bash -npm install --save lodash -``` - -T> When installing a package that will be bundled into your production bundle, you should use `npm install --save`. If you're installing a package for development purposes (e.g. a linter, testing libraries, etc.) then you should use `npm install --save-dev`. More information can be found in the [npm documentation](https://docs.npmjs.com/cli/install). - -Now, lets import `lodash` in our script: - -__src/index.js__ - -``` diff -+ import _ from 'lodash'; -+ - function component() { - let element = document.createElement('div'); - -- // Lodash, currently included via a script, is required for this line to work - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -Now, since we'll be bundling our scripts, we have to update our `index.html` file. Let's remove the lodash `<script>`, as we now `import` it, and modify the other `<script>` tag to load the bundle, instead of the raw `/src` file: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> - <title>Getting Started</title> -- <script src="https://unpkg.com/lodash@4.16.6"></script> - </head> - <body> -- <script src="./src/index.js"></script> -+ <script src="main.js"></script> - </body> - </html> -``` - -In this setup, `index.js` explicitly requires `lodash` to be present, and binds it as `_` (no global scope pollution). By stating what dependencies a module needs, webpack can use this information to build a dependency graph. It then uses the graph to generate an optimized bundle where scripts will be executed in the correct order. - -With that said, let's run `npx webpack`, which will take our script at `src/index.js` as the [entry point](/concepts/entry-points), and will generate `dist/main.js` as the [output](/concepts/output). The `npx` command, which ships with Node 8.2/npm 5.2.0 or higher, runs the webpack binary (`./node_modules/.bin/webpack`) of the webpack package we installed in the beginning: - -``` bash -npx webpack - -... -Built at: 13/06/2018 11:52:07 - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ -``` - -T> Your output may vary a bit, but if the build is successful then you are good to go. Also, don't worry about the warning, we'll tackle that later. - -Open `index.html` in your browser and, if everything went right, you should see the following text: 'Hello webpack'. - - -## Modules - -The [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) statements have been standardized in [ES2015](https://babeljs.io/learn-es2015/) and [are supported in most browsers](https://caniuse.com/#search=modules). Some older browsers still lag behind but webpack supports modules out of the box. - -Behind the scenes, webpack actually "transpiles" the code so that older browsers can also run it. If you inspect `dist/main.js`, you might be able to see how webpack does this, it's quite ingenious! Besides `import` and `export`, webpack supports various other module syntaxes as well, see [Module API](/api/module-methods) for more information. - -Note that webpack will not alter any code other than `import` and `export` statements. If you are using other [ES2015 features](http://es6-features.org/), make sure to [use a transpiler](/loaders/#transpiling) such as [Babel](https://babeljs.io/) or [Bublé](https://buble.surge.sh/guide/) via webpack's [loader system](/concepts/loaders/). - - -## Using a Configuration - -As of version 4, webpack doesn't require any configuration, but most projects will need a more complex setup, which is why webpack supports a [configuration file](/concepts/configuration). This is much more efficient than having to manually type in a lot of commands in the terminal, so let's create one: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- webpack.config.js - |- /dist - |- index.html - |- /src - |- index.js -``` - -__webpack.config.js__ - -``` javascript -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'main.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -Now, let's run the build again but instead using our new configuration file: - -``` bash -npx webpack --config webpack.config.js - -... - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ -``` - -T> If a `webpack.config.js` is present, the `webpack` command picks it up by default. We use the `--config` option here only to show that you can pass a config of any name. This will be useful for more complex configurations that need to be split into multiple files. - -A configuration file allows far more flexibility than simple CLI usage. We can specify loader rules, plugins, resolve options and many other enhancements this way. See the [configuration documentation](/configuration) to learn more. - - -## NPM Scripts - -Given it's not particularly fun to run a local copy of webpack from the CLI, we can set up a little shortcut. Let's adjust our _package.json_ by adding an [npm script](https://docs.npmjs.com/misc/scripts): - -__package.json__ - -``` diff - { - "name": "webpack-demo", - "version": "1.0.0", - "description": "", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", -+ "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "webpack": "^4.20.2", - "webpack-cli": "^3.1.2" - }, - "dependencies": { - "lodash": "^4.17.5" - } - } -``` - -Now the `npm run build` command can be used in place of the `npx` command we used earlier. Note that within `scripts` we can reference locally installed npm packages by name the same way we did with `npx`. This convention is the standard in most npm-based projects because it allows all contributors to use the same set of common scripts (each with flags like `--config` if necessary). - -Now run the following command and see if your script alias works: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/. -``` - -T> Custom parameters can be passed to webpack by adding two dashes between the `npm run build` command and your parameters, e.g. `npm run build -- --colors`. - - -## Conclusion - -Now that you have a basic build together you should move on to the next guide [`Asset Management`](/guides/asset-management) to learn how to manage assets like images and fonts with webpack. At this point, your project should look like this: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist - |- main.js - |- index.html -|- /src - |- index.js -|- /node_modules -``` - -T> If you're using npm 5, you'll probably also see a `package-lock.json` file in your directory. - -If you want to learn more about webpack's design, you can check out the [basic concepts](/concepts) and [configuration](/configuration) pages. Furthermore, the [API](/api) section digs into the various interfaces webpack offers. - - -# Asset Management - -If you've been following the guides from the start, you will now have a small project that shows "Hello webpack". Now let's try to incorporate some other assets, like images, to see how they can be handled. - -Prior to webpack, front-end developers would use tools like grunt and gulp to process these assets and move them from their `/src` folder into their `/dist` or `/build` directory. The same idea was used for JavaScript modules, but tools like webpack will __dynamically bundle__ all dependencies (creating what's known as a [dependency graph](/concepts/dependency-graph)). This is great because every module now _explicitly states its dependencies_ and we'll avoid bundling modules that aren't in use. - -One of the coolest webpack features is that you can also _include any other type of file_, besides JavaScript, for which there is a loader. This means that the same benefits listed above for JavaScript (e.g. explicit dependencies) can be applied to everything used in building a website or web app. Let's start with CSS, as you may already be familiar with that setup. - -## Setup - -Let's make a minor change to our project before we get started: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> -- <title>Getting Started</title> -+ <title>Asset Management</title> - </head> - <body> -- <script src="./main.js"></script> -+ <script src="./bundle.js"></script> - </body> - </html> -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { -- filename: 'main.js', -+ filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - - -## Loading CSS - -In order to `import` a CSS file from within a JavaScript module, you need to install and add the [style-loader](/loaders/style-loader) and [css-loader](/loaders/css-loader) to your [`module` configuration](/configuration/module): - -``` bash -npm install --save-dev style-loader css-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ module: { -+ rules: [ -+ { -+ test: /\.css$/, -+ use: [ -+ 'style-loader', -+ 'css-loader' -+ ] -+ } -+ ] -+ } - }; -``` - -T> webpack uses a regular expression to determine which files it should look for and serve to a specific loader. In this case any file that ends with `.css` will be served to the `style-loader` and the `css-loader`. - -This enables you to `import './style.css'` into the file that depends on that styling. Now, when that module is run, a `<style>` tag with the stringified css will be inserted into the `<head>` of your html file. - -Let's try it out by adding a new `style.css` file to our project and import it in our `index.js`: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- style.css - |- index.js - |- /node_modules -``` - -__src/style.css__ - -``` css -.hello { - color: red; -} -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import './style.css'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.classList.add('hello'); - - return element; - } - - document.body.appendChild(component()); -``` - -Now run your build command: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -bundle.js 76.4 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -Open up `index.html` in your browser again and you should see that `Hello webpack` is now styled in red. To see what webpack did, inspect the page (don't view the page source, as it won't show you the result) and look at the page's head tags. It should contain our style block that we imported in `index.js`. - -Note that you can, and in most cases should, [minimize css](/plugins/mini-css-extract-plugin/#minimizing-for-production) for better load times in production. On top of that, loaders exist for pretty much any flavor of CSS you can think of -- [postcss](/loaders/postcss-loader), [sass](/loaders/sass-loader), and [less](/loaders/less-loader) to name a few. - - -## Loading Images - -So now we're pulling in our CSS, but what about our images like backgrounds and icons? Using the [file-loader](/loaders/file-loader) we can easily incorporate those in our system as well: - -``` bash -npm install --save-dev file-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, -+ { -+ test: /\.(png|svg|jpg|gif)$/, -+ use: [ -+ 'file-loader' -+ ] -+ } - ] - } - }; -``` - -Now, when you `import MyImage from './my-image.png'`, that image will be processed and added to your `output` directory _and_ the `MyImage` variable will contain the final url of that image after processing. When using the [css-loader](/loaders/css-loader), as shown above, a similar process will occur for `url('./my-image.png')` within your CSS. The loader will recognize this is a local file, and replace the `'./my-image.png'` path with the final path to the image in your `output` directory. The [html-loader](/loaders/html-loader) handles `<img src="./my-image.png" />` in the same manner. - -Let's add an image to our project and see how this works, you can use any image you like: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; - import './style.css'; -+ import Icon from './icon.png'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - element.classList.add('hello'); - -+ // Add the image to our existing div. -+ var myIcon = new Image(); -+ myIcon.src = Icon; -+ -+ element.appendChild(myIcon); - - return element; - } - - document.body.appendChild(component()); -``` - -__src/style.css__ - -``` diff - .hello { - color: red; -+ background: url('./icon.png'); - } -``` - -Let's create a new build and open up the index.html file again: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] - bundle.js 76.7 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -If all went well, you should now see your icon as a repeating background, as well as an `img` element beside our `Hello webpack` text. If you inspect this element, you'll see that the actual filename has changed to something like `5c999da72346a995e7e2718865d019c8.png`. This means webpack found our file in the `src` folder and processed it! - -T> A logical next step from here is minifying and optimizing your images. Check out the [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader) and [url-loader](/loaders/url-loader) for more on how you can enhance your image loading process. - - -## Loading Fonts - -So what about other assets like fonts? The file and url loaders will take any file you load through them and output it to your build directory. This means we can use them for any kind of file, including fonts. Let's update our `webpack.config.js` to handle font files: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, - { - test: /\.(png|svg|jpg|gif)$/, - use: [ - 'file-loader' - ] - }, -+ { -+ test: /\.(woff|woff2|eot|ttf|otf)$/, -+ use: [ -+ 'file-loader' -+ ] -+ } - ] - } - }; -``` - -Add some font files to your project: - -__project__ - - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- my-font.woff -+ |- my-font.woff2 - |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -With the loader configured and fonts in place, you can incorporate them via an `@font-face` declaration. The local `url(...)` directive will be picked up by webpack just as it was with the image: - -__src/style.css__ - -``` diff -+ @font-face { -+ font-family: 'MyFont'; -+ src: url('./my-font.woff2') format('woff2'), -+ url('./my-font.woff') format('woff'); -+ font-weight: 600; -+ font-style: normal; -+ } - - .hello { - color: red; -+ font-family: 'MyFont'; - background: url('./icon.png'); - } -``` - -Now run a new build and let's see if webpack handled our fonts: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -5439466351d432b73fdb518c6ae9654a.woff2 19.5 KiB [emitted] - 387c65cc923ad19790469cfb5b7cb583.woff 23.4 KiB [emitted] - da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] - bundle.js 77 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -Open up `index.html` again and see if our `Hello webpack` text has changed to the new font. If all is well, you should see the changes. - - -## Loading Data - -Another useful asset that can be loaded is data, like JSON files, CSVs, TSVs, and XML. Support for JSON is actually built-in, similar to NodeJS, meaning `import Data from './data.json'` will work by default. To import CSVs, TSVs, and XML you could use the [csv-loader](https://github.com/theplatapi/csv-loader) and [xml-loader](https://github.com/gisikw/xml-loader). Let's handle loading all three: - -``` bash -npm install --save-dev csv-loader xml-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, - { - test: /\.(png|svg|jpg|gif)$/, - use: [ - 'file-loader' - ] - }, - { - test: /\.(woff|woff2|eot|ttf|otf)$/, - use: [ - 'file-loader' - ] - }, -+ { -+ test: /\.(csv|tsv)$/, -+ use: [ -+ 'csv-loader' -+ ] -+ }, -+ { -+ test: /\.xml$/, -+ use: [ -+ 'xml-loader' -+ ] -+ } - ] - } - }; -``` - -Add some data files to your project: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- data.xml - |- my-font.woff - |- my-font.woff2 - |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -__src/data.xml__ - -``` xml -<?xml version="1.0" encoding="UTF-8"?> -<note> - <to>Mary</to> - <from>John</from> - <heading>Reminder</heading> - <body>Call Cindy on Tuesday</body> -</note> -``` - -Now you can `import` any one of those four types of data (JSON, CSV, TSV, XML) and the `Data` variable you import it to will contain parsed JSON for easy consumption: - -__src/index.js__ - -``` diff - import _ from 'lodash'; - import './style.css'; - import Icon from './icon.png'; -+ import Data from './data.xml'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - element.classList.add('hello'); - - // Add the image to our existing div. - var myIcon = new Image(); - myIcon.src = Icon; - - element.appendChild(myIcon); - -+ console.log(Data); - - return element; - } - - document.body.appendChild(component()); -``` - -When you open `index.html` and look at your console in your developer tools, you should be able to see your imported data being logged to the console! - -T> This can be especially helpful when implementing some sort of data visualization using a tool like [d3](https://github.com/d3). Instead of making an ajax request and parsing the data at runtime you can load it into your module during the build process so that the parsed data is ready to go as soon as the module hits the browser. - - -## Global Assets - -The coolest part of everything mentioned above, is that loading assets this way allows you to group modules and assets together in a more intuitive way. Instead of relying on a global `/assets` directory that contains everything, you can group assets with the code that uses them. For example, a structure like this can be very useful: - -``` diff -- |- /assets -+ |– /components -+ | |– /my-component -+ | | |– index.jsx -+ | | |– index.css -+ | | |– icon.svg -+ | | |– img.png -``` - -This setup makes your code a lot more portable as everything that is closely coupled now lives together. Let's say you want to use `/my-component` in another project, simply copy or move it into the `/components` directory over there. As long as you've installed any _external dependencies_ and your _configuration has the same loaders_ defined, you should be good to go. - -However, let's say you're locked into your old ways or you have some assets that are shared between multiple components (views, templates, modules, etc.). It's still possible to store these assets in a base directory and even use [aliasing](/configuration/resolve#resolve-alias) to make them easier to `import`. - - -## Wrapping up - -For the next guides we won't be using all the different assets we've used in this guide, so let's do some cleanup so we're prepared for the next piece of the guides [Output Management](https://webpack.js.org/guides/output-management/): - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -- |- data.xml -- |- my-font.woff -- |- my-font.woff2 -- |- icon.png -- |- style.css - |- index.js - |- /node_modules -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- module: { -- rules: [ -- { -- test: /\.css$/, -- use: [ -- 'style-loader', -- 'css-loader' -- ] -- }, -- { -- test: /\.(png|svg|jpg|gif)$/, -- use: [ -- 'file-loader' -- ] -- }, -- { -- test: /\.(woff|woff2|eot|ttf|otf)$/, -- use: [ -- 'file-loader' -- ] -- }, -- { -- test: /\.(csv|tsv)$/, -- use: [ -- 'csv-loader' -- ] -- }, -- { -- test: /\.xml$/, -- use: [ -- 'xml-loader' -- ] -- } -- ] -- } - }; -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -- import './style.css'; -- import Icon from './icon.png'; -- import Data from './data.xml'; -- - function component() { - var element = document.createElement('div'); -- -- // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- element.classList.add('hello'); -- -- // Add the image to our existing div. -- var myIcon = new Image(); -- myIcon.src = Icon; -- -- element.appendChild(myIcon); -- -- console.log(Data); - - return element; - } - - document.body.appendChild(component()); -``` - - -## Next guide - -Let's move on to [Output Management](https://webpack.js.org/guides/output-management/) - - -## Further Reading - -- [Loading Fonts](https://survivejs.com/webpack/loading/fonts/) on SurviveJS - - -# Output Management - -T> This guide extends on code examples found in the [`Asset Management`](/guides/asset-management) guide. - -So far we've manually included all our assets in our `index.html` file, but as your application grows and once you start [using hashes in filenames](/guides/caching) and outputting [multiple bundles](/guides/code-splitting), it will be difficult to keep managing your `index.html` file manually. However, a few plugins exist that will make this process much easier to manage. - -## Preparation - -First, let's adjust our project a little bit: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js -+ |- print.js - |- /node_modules -``` - -Let's add some logic to our `src/print.js` file: - -__src/print.js__ - -``` js -export default function printMe() { - console.log('I get called from print.js!'); -} -``` - -And use that function in our `src/index.js` file: - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); -+ var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - -+ btn.innerHTML = 'Click me and check the console!'; -+ btn.onclick = printMe; -+ -+ element.appendChild(btn); - - return element; - } - - document.body.appendChild(component()); -``` - -Let's also update our `dist/index.html` file, in preparation for webpack to split out entries: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> -- <title>Asset Management</title> -+ <title>Output Management</title> -+ <script src="./print.bundle.js"></script> - </head> - <body> -- <script src="./bundle.js"></script> -+ <script src="./app.bundle.js"></script> - </body> - </html> -``` - -Now adjust the config. We'll be adding our `src/print.js` as a new entry point (`print`) and we'll change the output as well, so that it will dynamically generate bundle names, based on the entry point names: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { -- entry: './src/index.js', -+ entry: { -+ app: './src/index.js', -+ print: './src/print.js' -+ }, - output: { -- filename: 'bundle.js', -+ filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Let's run `npm run build` and see what this generates: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 545 kB 0, 1 [emitted] [big] app -print.bundle.js 2.74 kB 1 [emitted] print -... -``` - -We can see that webpack generates our `print.bundle.js` and `app.bundle.js` files, which we also specified in our `index.html` file. if you open `index.html` in your browser, you can see what happens when you click the button. - -But what would happen if we changed the name of one of our entry points, or even added a new one? The generated bundles would be renamed on a build, but our `index.html` file would still reference the old names. Let's fix that with the [`HtmlWebpackPlugin`](/plugins/html-webpack-plugin). - - -## Setting up HtmlWebpackPlugin - -First install the plugin and adjust the `webpack.config.js` file: - -``` bash -npm install --save-dev html-webpack-plugin -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, -+ plugins: [ -+ new HtmlWebpackPlugin({ -+ title: 'Output Management' -+ }) -+ ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Before we do a build, you should know that the `HtmlWebpackPlugin` by default will generate its own `index.html` file, even though we already have one in the `dist/` folder. This means that it will replace our `index.html` file with a newly generated one. Let's see what happens when we do an `npm run build`: - -``` bash -... - Asset Size Chunks Chunk Names - print.bundle.js 544 kB 0 [emitted] [big] print - app.bundle.js 2.81 kB 1 [emitted] app - index.html 249 bytes [emitted] -... -``` - -If you open `index.html` in your code editor, you'll see that the `HtmlWebpackPlugin` has created an entirely new file for you and that all the bundles are automatically added. - -If you want to learn more about all the features and options that the `HtmlWebpackPlugin` provides, then you should read up on it on the [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin) repo. - -You can also take a look at [`html-webpack-template`](https://github.com/jaketrent/html-webpack-template) which provides a couple of extra features in addition to the default template. - - -## Cleaning up the `/dist` folder - -As you might have noticed over the past guides and code example, our `/dist` folder has become quite cluttered. Webpack will generate the files and put them in the `/dist` folder for you, but it doesn't keep track of which files are actually in use by your project. - -In general it's good practice to clean the `/dist` folder before each build, so that only used files will be generated. Let's take care of that. - -A popular plugin to manage this is the [`clean-webpack-plugin`](https://www.npmjs.com/package/clean-webpack-plugin) so let's install and configure it. - -``` bash -npm install --save-dev clean-webpack-plugin -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); -+ const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ -+ new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Output Management' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Now run an `npm run build` and inspect the `/dist` folder. If everything went well you should now only see the files generated from the build and no more old files! - - -## The Manifest - -You might be wondering how webpack and its plugins seem to "know" what files are being generated. The answer is in the manifest that webpack keeps to track how all the modules map to the output bundles. If you're interested in managing webpack's [`output`](/configuration/output) in other ways, the manifest would be a good place to start. - -The manifest data can be extracted into a json file for easy consumption using the [`WebpackManifestPlugin`](https://github.com/danethurber/webpack-manifest-plugin). - -We won't go through a full example of how to use this plugin within your projects, but you can read up on [the concept page](/concepts/manifest) and the [caching guide](/guides/caching) to find out how this ties into long term caching. - - -## Conclusion - -Now that you've learned about dynamically adding bundles to your HTML, let's dive into the [development guide](/guides/development). Or, if you want to dig into more advanced topics, we would recommend heading over to the [code splitting guide](/guides/code-splitting). - - -# Development - -T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. - -If you've been following the guides, you should have a solid understanding of some of the webpack basics. Before we continue, let's look into setting up a development environment to make our lives a little easier. - -W> The tools in this guide are __only meant for development__, please __avoid__ using them in production! - -Before proceeding lets first set [`mode` to `'development'`](/concepts/mode/#mode-development). - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { -+ mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -## Using source maps - -When webpack bundles your source code, it can become difficult to track down errors and warnings to their original location. For example, if you bundle three source files (`a.js`, `b.js`, and `c.js`) into one bundle (`bundle.js`) and one of the source files contains an error, the stack trace will simply point to `bundle.js`. This isn't always helpful as you probably want to know exactly which source file the error came from. - -In order to make it easier to track down errors and warnings, JavaScript offers [source maps](http://blog.teamtreehouse.com/introduction-source-maps), which maps your compiled code back to your original source code. If an error originates from `b.js`, the source map will tell you exactly that. - -There are a lot of [different options](/configuration/devtool) available when it comes to source maps. Be sure to check them out so you can configure them to your needs. - -For this guide, let's use the `inline-source-map` option, which is good for illustrative purposes (though not for production): - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, -+ devtool: 'inline-source-map', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Now let's make sure we have something to debug, so let's create an error in our `print.js` file: - -__src/print.js__ - -``` diff - export default function printMe() { -- console.log('I get called from print.js!'); -+ cosnole.log('I get called from print.js!'); - } -``` - -Run an `npm run build`, it should compile to something like this: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 1.44 MB 0, 1 [emitted] [big] app -print.bundle.js 6.43 kB 1 [emitted] print - index.html 248 bytes [emitted] -... -``` - -Now open the resulting `index.html` file in your browser. Click the button and look in your console where the error is displayed. The error should say something like this: - - ``` bash - Uncaught ReferenceError: cosnole is not defined - at HTMLButtonElement.printMe (print.js:2) - ``` - -We can see that the error also contains a reference to the file (`print.js`) and line number (2) where the error occurred. This is great because now we know exactly where to look in order to fix the issue. - - -## Choosing a Development Tool - -W> Some text editors have a "safe write" function that might interfere with some of the following tools. Read [Adjusting Your text Editor](#adjusting-your-text-editor) for a solution to these issues. - -It quickly becomes a hassle to manually run `npm run build` every time you want to compile your code. - -There are a couple of different options available in webpack that help you automatically compile your code whenever it changes: - - 1. webpack's Watch Mode - 2. webpack-dev-server - 3. webpack-dev-middleware - -In most cases, you probably would want to use `webpack-dev-server`, but let's explore all of the above options. - - -### Using Watch Mode - -You can instruct webpack to "watch" all files within your dependency graph for changes. If one of these files is updated, the code will be recompiled so you don't have to run the full build manually. - -Let's add an npm script that will start webpack's Watch Mode: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", -+ "watch": "webpack --watch", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now run `npm run watch` from the command line and see how webpack compiles your code. -You can see that it doesn't exit the command line because the script is currently watching your files. - -Now, while webpack is watching your files, let's remove the error we introduced earlier: - -__src/print.js__ - -``` diff - export default function printMe() { -- cosnole.log('I get called from print.js!'); -+ console.log('I get called from print.js!'); - } -``` - -Now save your file and check the terminal window. You should see that webpack automatically recompiles the changed module! - -The only downside is that you have to refresh your browser in order to see the changes. It would be much nicer if that would happen automatically as well, so let's try `webpack-dev-server` which will do exactly that. - - -### Using webpack-dev-server - -The `webpack-dev-server` provides you with a simple web server and the ability to use live reloading. Let's set it up: - -``` bash -npm install --save-dev webpack-dev-server -``` - -Change your config file to tell the dev server where to look for files: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - devtool: 'inline-source-map', -+ devServer: { -+ contentBase: './dist' -+ }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -This tells `webpack-dev-server` to serve the files from the `dist` directory on `localhost:8080`. - -W> webpack-dev-server doesn't write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server's root path. If your page expects to find the bundle files in different path, you can change this with the [`publicPath`](/configuration/dev-server/#devserver-publicpath-) option in the dev server's configuration. - -Let's add a script to easily run the dev server as well: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "watch": "webpack --watch", -+ "start": "webpack-dev-server --open", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now we can run `npm start` from the command line and we will see our browser automatically loading up our page. If you now change any of the source files and save them, the web server will automatically reload after the code has been compiled. Give it a try! - -The `webpack-dev-server` comes with many configurable options. Head over to the [documentation](/configuration/dev-server) to learn more. - -T> Now that your server is working, you might want to give [Hot Module Replacement](/guides/hot-module-replacement) a try! - - -### Using webpack-dev-middleware - -`webpack-dev-middleware` is a wrapper that will emit files processed by webpack to a server. This is used in `webpack-dev-server` internally, however it's available as a separate package to allow more custom setups if desired. We'll take a look at an example that combines webpack-dev-middleware with an express server. - -Let's install `express` and `webpack-dev-middleware` so we can get started: - -``` bash -npm install --save-dev express webpack-dev-middleware -``` - -Now we need to make some adjustments to our webpack configuration file in order to make sure the middleware will function correctly: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Output Management' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist'), -+ publicPath: '/' - } - }; -``` - -The `publicPath` will be used within our server script as well in order to make sure files are served correctly on `http://localhost:3000`. We'll specify the port number later. The next step is setting up our custom `express` server: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js -+ |- server.js - |- /dist - |- /src - |- index.js - |- print.js - |- /node_modules -``` - -__server.js__ - -```javascript -const express = require('express'); -const webpack = require('webpack'); -const webpackDevMiddleware = require('webpack-dev-middleware'); - -const app = express(); -const config = require('./webpack.config.js'); -const compiler = webpack(config); - -// Tell express to use the webpack-dev-middleware and use the webpack.config.js -// configuration file as a base. -app.use(webpackDevMiddleware(compiler, { - publicPath: config.output.publicPath -})); - -// Serve the files on port 3000. -app.listen(3000, function () { - console.log('Example app listening on port 3000!\n'); -}); -``` - -Now add an npm script to make it a little easier to run the server: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "watch": "webpack --watch", - "start": "webpack-dev-server --open", -+ "server": "node server.js", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "express": "^4.15.3", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "webpack-dev-middleware": "^1.12.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now in your terminal run `npm run server`, it should give you an output similar to this: - -``` bash -Example app listening on port 3000! -... - Asset Size Chunks Chunk Names - app.bundle.js 1.44 MB 0, 1 [emitted] [big] app -print.bundle.js 6.57 kB 1 [emitted] print - index.html 306 bytes [emitted] -... -webpack: Compiled successfully. -``` - -Now fire up your browser and go to `http://localhost:3000`. You should see your webpack app running and functioning! - -T> If you would like to know more about how Hot Module Replacement works, we recommend you read the [Hot Module Replacement](/guides/hot-module-replacement/) guide. - - -## Adjusting Your Text Editor - -When using automatic compilation of your code, you could run into issues when saving your files. Some editors have a "safe write" feature that can potentially interfere with recompilation. - -To disable this feature in some common editors, see the list below: - -- __Sublime Text 3__: Add `atomic_save: 'false'` to your user preferences. -- __JetBrains IDEs (e.g. WebStorm)__: Uncheck "Use safe write" in `Preferences > Appearance & Behavior > System Settings`. -- __Vim__: Add `:set backupcopy=yes` to your settings. - - -## Conclusion - -Now that you've learned how to automatically compile your code and run a simple development server, you can check out the next guide, which will cover [Hot Module Replacement](/guides/hot-module-replacement). - - -# Hot Module Replacement - -T> This guide extends on code examples found in the [Development](/guides/development) guide. - -Hot Module Replacement (or HMR) is one of the most useful features offered by webpack. It allows all kinds of modules to be updated at runtime without the need for a full refresh. This page focuses on __implementation__ while the [concepts page](/concepts/hot-module-replacement) gives more details on how it works and why it's useful. - -W> __HMR__ is not intended for use in production, meaning it should only be used in development. See the [building for production guide](/guides/production) for more information. - - -## Enabling HMR - -This feature is great for productivity. All we need to do is update our [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration, and use webpack's built in HMR plugin. We'll also remove the entry point for `print.js` as it will now be consumed by the `index.js` module. - -T> If you took the route of using `webpack-dev-middleware` instead of `webpack-dev-server`, please use the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom server or application. - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const webpack = require('webpack'); - - module.exports = { - entry: { -- app: './src/index.js', -- print: './src/print.js' -+ app: './src/index.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist', -+ hot: true - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Hot Module Replacement' - }), -+ new webpack.HotModuleReplacementPlugin() - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -T> You can use the CLI to modify the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration with the following command: `webpack-dev-server --hotOnly`. - -Now let's update the `index.js` file so that when a change inside `print.js` is detected we tell webpack to accept the updated module. - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; - - element.appendChild(btn); - - return element; - } - - document.body.appendChild(component()); -+ -+ if (module.hot) { -+ module.hot.accept('./print.js', function() { -+ console.log('Accepting the updated printMe module!'); -+ printMe(); -+ }) -+ } -``` - -Start changing the `console.log` statement in `print.js`, and you should see the following output in the browser console. - -__print.js__ - -``` diff - export default function printMe() { -- console.log('I get called from print.js!'); -+ console.log('Updating print.js...') - } -``` - -__console__ - -``` diff -[HMR] Waiting for update signal from WDS... -main.js:4395 [WDS] Hot Module Replacement enabled. -+ 2main.js:4395 [WDS] App updated. Recompiling... -+ main.js:4395 [WDS] App hot update... -+ main.js:4330 [HMR] Checking for updates on the server... -+ main.js:10024 Accepting the updated printMe module! -+ 0.4b8ee77….hot-update.js:10 Updating print.js... -+ main.js:4330 [HMR] Updated modules: -+ main.js:4330 [HMR] - 20 -``` - - -## Via the Node.js API - -When using Webpack Dev Server with the Node.js API, don't put the dev server options on the webpack config object. Instead, pass them as a second parameter upon creation. For example: - -`new WebpackDevServer(compiler, options)` - -To enable HMR, you also need to modify your webpack configuration object to include the HMR entry points. The `webpack-dev-server` package includes a method called `addDevServerEntrypoints` which you can use to do this. Here's a small example of how that might look: - -__dev-server.js__ - -``` javascript -const webpackDevServer = require('webpack-dev-server'); -const webpack = require('webpack'); - -const config = require('./webpack.config.js'); -const options = { - contentBase: './dist', - hot: true, - host: 'localhost' -}; - -webpackDevServer.addDevServerEntrypoints(config, options); -const compiler = webpack(config); -const server = new webpackDevServer(compiler, options); - -server.listen(5000, 'localhost', () => { - console.log('dev server listening on port 5000'); -}); -``` - -T> If you're [using `webpack-dev-middleware`](/guides/development#using-webpack-dev-middleware), check out the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom dev server. - - -## Gotchas - -Hot Module Replacement can be tricky. To show this, let's go back to our working example. If you go ahead and click the button on the example page, you will realize the console is printing the old `printMe` function. - -This is happening because the button's `onclick` event handler is still bound to the original `printMe` function. - -To make this work with HMR we need to update that binding to the new `printMe` function using `module.hot.accept`: - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; // onclick event is bind to the original printMe function - - element.appendChild(btn); - - return element; - } - -- document.body.appendChild(component()); -+ let element = component(); // Store the element to re-render on print.js changes -+ document.body.appendChild(element); - - if (module.hot) { - module.hot.accept('./print.js', function() { - console.log('Accepting the updated printMe module!'); -- printMe(); -+ document.body.removeChild(element); -+ element = component(); // Re-render the "component" to update the click handler -+ document.body.appendChild(element); - }) - } -``` - -This is just one example, but there are many others that can easily trip people up. Luckily, there are a lot of loaders out there (some of which are mentioned below) that will make hot module replacement much easier. - - -## HMR with Stylesheets - -Hot Module Replacement with CSS is actually fairly straightforward with the help of the `style-loader`. This loader uses `module.hot.accept` behind the scenes to patch `<style>` tags when CSS dependencies are updated. - -First let's install both loaders with the following command: - -```bash -npm install --save-dev style-loader css-loader -``` - -Now let's update the configuration file to make use of the loader. - -__webpack.config.js__ - -```diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const webpack = require('webpack'); - - module.exports = { - entry: { - app: './src/index.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist', - hot: true - }, -+ module: { -+ rules: [ -+ { -+ test: /\.css$/, -+ use: ['style-loader', 'css-loader'] -+ } -+ ] -+ }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Hot Module Replacement' - }), - new webpack.HotModuleReplacementPlugin() - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Hot loading stylesheets is as easy as importing them into a module: - -__project__ - -``` diff - webpack-demo - | - package.json - | - webpack.config.js - | - /dist - | - bundle.js - | - /src - | - index.js - | - print.js -+ | - styles.css -``` - -__styles.css__ - -``` css -body { - background: blue; -} -``` - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; -+ import './styles.css'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; // onclick event is bind to the original printMe function - - element.appendChild(btn); - - return element; - } - - let element = component(); - document.body.appendChild(element); - - if (module.hot) { - module.hot.accept('./print.js', function() { - console.log('Accepting the updated printMe module!'); - document.body.removeChild(element); - element = component(); // Re-render the "component" to update the click handler - document.body.appendChild(element); - }) - } - -``` - -Change the style on `body` to `background: red;` and you should immediately see the page's background color change without a full refresh. - -__styles.css__ - -``` diff - body { -- background: blue; -+ background: red; - } -``` - - -## Other Code and Frameworks - -There are many other loaders and examples out in the community to make HMR interact smoothly with a variety of frameworks and libraries... - -- [React Hot Loader](https://github.com/gaearon/react-hot-loader): Tweak react components in real time. -- [Vue Loader](https://github.com/vuejs/vue-loader): This loader supports HMR for vue components out of the box. -- [Elm Hot Loader](https://github.com/fluxxu/elm-hot-loader): Supports HMR for the Elm programming language. -- [Angular HMR](https://github.com/gdi2290/angular-hmr): No loader necessary! A simple change to your main NgModule file is all that's required to have full control over the HMR APIs. - -T> If you know of any other loaders or plugins that help with or enhance Hot Module Replacement please submit a pull request to add to this list! - - -# Tree Shaking - -_Tree shaking_ is a term commonly used in the JavaScript context for dead-code elimination. It relies on the [static structure](http://exploringjs.com/es6/ch_modules.html#static-module-structure) of ES2015 module syntax, i.e. [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export). The name and concept have been popularized by the ES2015 module bundler [rollup](https://github.com/rollup/rollup). - -The webpack 2 release came with built-in support for ES2015 modules (alias _harmony modules_) as well as unused module export detection. The new webpack 4 release expands on this capability with a way to provide hints to the compiler via the `"sideEffects"` `package.json` property to denote which files in your project are "pure" and therefore safe to prune if unused. - -T> The remainder of this guide will stem from [Getting Started](/guides/getting-started). If you haven't read through that guide already, please do so now. - - -## Add a Utility - -Let's add a new utility file to our project, `src/math.js`, that exports two functions: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist - |- bundle.js - |- index.html -|- /src - |- index.js -+ |- math.js -|- /node_modules -``` - -__src/math.js__ - -```javascript -export function square(x) { - return x * x; -} - -export function cube(x) { - return x * x * x; -} -``` - -Set the `mode` configuration option to [development](/concepts/mode/#mode-development) to make sure that the bundle is not minified: - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') -- } -+ }, -+ mode: 'development', -+ optimization: { -+ usedExports: true -+ } -}; -``` - -With that in place, let's update our entry script to utilize one of these new methods and remove `lodash` for simplicity: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -+ import { cube } from './math.js'; - - function component() { -- var element = document.createElement('div'); -+ var element = document.createElement('pre'); - -- // Lodash, now imported by this script -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.innerHTML = [ -+ 'Hello webpack!', -+ '5 cubed is equal to ' + cube(5) -+ ].join('\n\n'); - - return element; - } - - document.body.appendChild(component()); -``` - -Note that we __did not `import` the `square` method__ from the `src/math.js` module. That function is what's known as "dead code", meaning an unused `export` that should be dropped. Now let's run our npm script, `npm run build`, and inspect the output bundle: - -__dist/bundle.js (around lines 90 - 100)__ - -```js -/* 1 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - 'use strict'; - /* unused harmony export square */ - /* harmony export (immutable) */ __webpack_exports__['a'] = cube; - function square(x) { - return x * x; - } - - function cube(x) { - return x * x * x; - } -}); -``` - -Note the `unused harmony export square` comment above. If you look at the code below it, you'll notice that `square` is not being imported, however, it is still included in the bundle. We'll fix that in the next section. - - -## Mark the file as side-effect-free - -In a 100% ESM module world, identifying side effects is straightforward. However, we aren't there just yet, so in the mean time it's necessary to provide hints to webpack's compiler on the "pureness" of your code. - -The way this is accomplished is the `"sideEffects"` package.json property. - -```json -{ - "name": "your-project", - "sideEffects": false -} -``` - -All the code noted above does not contain side effects, so we can simply mark the property as `false` to inform webpack that it can safely prune unused exports. - -T> A "side effect" is defined as code that performs a special behavior when imported, other than exposing one or more exports. An example of this are polyfills, which affect the global scope and usually do not provide an export. - -If your code did have some side effects though, an array can be provided instead: - -```json -{ - "name": "your-project", - "sideEffects": [ - "./src/some-side-effectful-file.js" - ] -} -``` - -The array accepts relative, absolute, and glob patterns to the relevant files. It uses [micromatch](https://github.com/micromatch/micromatch#matching-features) under the hood. - -T> Note that any imported file is subject to tree shaking. This means if you use something like `css-loader` in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode: - -```json -{ - "name": "your-project", - "sideEffects": [ - "./src/some-side-effectful-file.js", - "*.css" - ] -} -``` - -Finally, `"sideEffects"` can also be set from the [`module.rules` configuration option](/configuration/module/#module-rules). - -## Minify the Output - -So we've cued up our "dead code" to be dropped by using the `import` and `export` syntax, but we still need to drop it from the bundle. To do that set the `mode` configuration option to [`production`](/concepts/mode/#mode-production) configuration option. - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- mode: 'development', -- optimization: { -- usedExports: true -- } -+ mode: 'production' -}; -``` - -T> Note that the `--optimize-minimize` flag can be used to enable `TerserPlugin` as well. - -With that squared away, we can run another `npm run build` and see if anything has changed. - -Notice anything different about `dist/bundle.js`? Clearly the whole bundle is now minified and mangled, but, if you look carefully, you won't see the `square` function included but will see a mangled version of the `cube` function (`function r(e){return e*e*e}n.a=r`). With minification and tree shaking our bundle is now a few bytes smaller! While that may not seem like much in this contrived example, tree shaking can yield a significant decrease in bundle size when working on larger applications with complex dependency trees. - -T> [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) is needed for the tree shaking to work. It is added by `mode: "production"`. If you are not using it, remember to add the [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) manually. - -## Conclusion - -So, what we've learned is that in order to take advantage of _tree shaking_, you must... - -- Use ES2015 module syntax (i.e. `import` and `export`). -- Ensure no compilers transform your ES2015 module syntax into CommonJS modules (this is the default behavior of popular Babel preset @babel/preset-env - see [documentation](https://babeljs.io/docs/en/babel-preset-env#modules) for more details). -- Add a `"sideEffects"` property to your project's `package.json` file. -- Use [`production`](/concepts/mode/#mode-production) `mode` configuration option to enable [various optimizations](/concepts/mode/#usage) including minification and tree shaking. - -You can imagine your application as a tree. The source code and libraries you actually use represent the green, living leaves of the tree. Dead code represents the brown, dead leaves of the tree that are consumed by autumn. In order to get rid of the dead leaves, you have to shake the tree, causing them to fall. - -If you are interested in more ways to optimize your output, please jump to the next guide for details on building for [production](/guides/production). - - -# Production - -In this guide we'll dive into some of the best practices and utilities for building a production site or application. - -T> This walkthrough stems from [Tree Shaking](/guides/tree-shaking) and [Development](/guides/development). Please ensure you are familiar with the concepts/setup introduced in those guides before continuing on. - - -## Setup - -The goals of _development_ and _production_ builds differ greatly. In _development_, we want strong source mapping and a localhost server with live reloading or hot module replacement. In _production_, our goals shift to a focus on minified bundles, lighter weight source maps, and optimized assets to improve load time. With this logical separation at hand, we typically recommend writing __separate webpack configurations__ for each environment. - -While we will separate the _production_ and _development_ specific bits out, note that we'll still maintain a "common" configuration to keep things DRY. In order to merge these configurations together, we'll use a utility called [`webpack-merge`](https://github.com/survivejs/webpack-merge). With the "common" configuration in place, we won't have to duplicate code within the environment-specific configurations. - -Let's start by installing `webpack-merge` and splitting out the bits we've already worked on in previous guides: - -``` bash -npm install --save-dev webpack-merge -``` - -__project__ - -``` diff - webpack-demo - |- package.json -- |- webpack.config.js -+ |- webpack.common.js -+ |- webpack.dev.js -+ |- webpack.prod.js - |- /dist - |- /src - |- index.js - |- math.js - |- /node_modules -``` - -__webpack.common.js__ - -``` diff -+ const path = require('path'); -+ const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const HtmlWebpackPlugin = require('html-webpack-plugin'); -+ -+ module.exports = { -+ entry: { -+ app: './src/index.js' -+ }, -+ plugins: [ -+ new CleanWebpackPlugin(['dist']), -+ new HtmlWebpackPlugin({ -+ title: 'Production' -+ }) -+ ], -+ output: { -+ filename: '[name].bundle.js', -+ path: path.resolve(__dirname, 'dist') -+ } -+ }; -``` - -__webpack.dev.js__ - -``` diff -+ const merge = require('webpack-merge'); -+ const common = require('./webpack.common.js'); -+ -+ module.exports = merge(common, { -+ mode: 'development', -+ devtool: 'inline-source-map', -+ devServer: { -+ contentBase: './dist' -+ } -+ }); -``` - -__webpack.prod.js__ - -``` diff -+ const merge = require('webpack-merge'); -+ const common = require('./webpack.common.js'); -+ -+ module.exports = merge(common, { -+ mode: 'production', -+ }); -``` - -In `webpack.common.js`, we now have setup our `entry` and `output` configuration and we've included any plugins that are required for both environments. In `webpack.dev.js`, we've set ``mode`` to ``development``. Also, we've added the recommended `devtool` for that environment (strong source mapping), as well as our simple `devServer` configuration. Finally, in `webpack.prod.js`,``mode`` is set to ``production`` which loads `TerserPlugin` which was first introduced by the [tree shaking](/guides/tree-shaking) guide. - -Note the use of `merge()` in the environment-specific configurations to easily include our common configuration in `dev` and `prod`. The `webpack-merge` tool offers a variety of advanced features for merging but for our use case we won't need any of that. - - -## NPM Scripts - -Now let's repoint our `scripts` to the new configurations. We'll use the _development_ one for our `webpack-dev-server`, `npm start`, script and the _production_ one for our `npm run build` script: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "src/index.js", - "scripts": { -- "start": "webpack-dev-server --open", -+ "start": "webpack-dev-server --open --config webpack.dev.js", -- "build": "webpack" -+ "build": "webpack --config webpack.prod.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.17", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "express": "^4.15.3", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "webpack-dev-middleware": "^1.12.0", - "webpack-dev-server": "^2.9.1", - "webpack-merge": "^4.1.0", - "xml-loader": "^1.2.1" - } - } -``` - -Feel free to run those scripts and see how the output changes as we continue adding to our _production_ configuration. - - -## Specify the Mode - -Many libraries will key off the `process.env.NODE_ENV` variable to determine what should be included in the library. For example, when not in _production_ some libraries may add additional logging and testing to make debugging easier. However, with `process.env.NODE_ENV === 'production'` they might drop or add significant portions of code to optimize how things run for your actual users. Since webpack v4, specifying [`mode`](/concepts/mode/) automatically configures [`DefinePlugin`](/plugins/define-plugin) for you: - -__webpack.prod.js__ - -``` diff - const merge = require('webpack-merge'); - const common = require('./webpack.common.js'); - - module.exports = merge(common, { - mode: 'production', - }); -``` - -T> Technically, `NODE_ENV` is a system environment variable that Node.js exposes into running scripts. It is used by convention to determine dev-vs-prod behavior by server tools, build scripts, and client-side libraries. Contrary to expectations, `process.env.NODE_ENV` is not set to `"production"` __within__ the build script `webpack.config.js`, see [#2537](https://github.com/webpack/webpack/issues/2537). Thus, conditionals like `process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'` within webpack configurations do not work as expected. - -If you're using a library like [`react`](https://reactjs.org/), you should actually see a significant drop in bundle size after adding this plugin. Also note that any of our local `/src` code can key off of this as well, so the following check would be valid: - -__src/index.js__ - -``` diff - import { cube } from './math.js'; -+ -+ if (process.env.NODE_ENV !== 'production') { -+ console.log('Looks like we are in development mode!'); -+ } - - function component() { - var element = document.createElement('pre'); - - element.innerHTML = [ - 'Hello webpack!', - '5 cubed is equal to ' + cube(5) - ].join('\n\n'); - - return element; - } - - document.body.appendChild(component()); -``` - - -## Minification - -webpack v4+ will minify your code by default in [`production mode`](/concepts/mode/#mode-production). - -Note that while the [`TerserPlugin`](/plugins/terser-webpack-plugin) is a great place to start for minification and being used by default, there are other options out there. Here are a few more popular ones: - -- [`BabelMinifyWebpackPlugin`](https://github.com/webpack-contrib/babel-minify-webpack-plugin) -- [`ClosureCompilerPlugin`](https://github.com/roman01la/webpack-closure-compiler) - -If you decide to try another minification plugin, just make sure your new choice also drops dead code as described in the [tree shaking](/guides/tree-shaking) guide and provide it as the [`optimization.minimizer`](/configuration/optimization/#optimization-minimizer). - - -## Source Mapping - -We encourage you to have source maps enabled in production, as they are useful for debugging as well as running benchmark tests. That said, you should choose one with a fairly quick build speed that's recommended for production use (see [`devtool`](/configuration/devtool)). For this guide, we'll use the `source-map` option in _production_ as opposed to the `inline-source-map` we used in _development_: - -__webpack.prod.js__ - -``` diff - const merge = require('webpack-merge'); - const common = require('./webpack.common.js'); - - module.exports = merge(common, { - mode: 'production', -+ devtool: 'source-map' - }); -``` - -T> Avoid `inline-***` and `eval-***` use in production as they can increase bundle size and reduce the overall performance. - - -## Minimize CSS - -It is crucial to minimize your CSS on production, please see [Minimizing for Production](/plugins/mini-css-extract-plugin/#minimizing-for-production) section. - - -## CLI Alternatives - -Some of what has been described above is also achievable via the command line. For example, the `--optimize-minimize` flag will include the `TerserPlugin` behind the scenes. The `--define process.env.NODE_ENV="'production'"` will do the same for the `DefinePlugin` instance described above. And, `webpack -p` will automatically invoke both those flags and thus the plugins to be included. - -While these short hand methods are nice, we usually recommend just using the configuration as it's better to understand exactly what is being done for you in both cases. The configuration also gives you more control on fine tuning other options within both plugins. - - -# Code Splitting - -T> This guide extends the examples provided in [Getting Started](/guides/getting-started) and [Output Management](/guides/output-management). Please make sure you are at least familiar with the examples provided in them. - -Code splitting is one of the most compelling features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel. It can be used to achieve smaller bundles and control resource load prioritization which, if used correctly, can have a major impact on load time. - -There are three general approaches to code splitting available: - -- Entry Points: Manually split code using [`entry`](/configuration/entry-context) configuration. -- Prevent Duplication: Use the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) to dedupe and split chunks. -- Dynamic Imports: Split code via inline function calls within modules. - - -## Entry Points - -This is by far the easiest, and most intuitive, way to split code. However, it is more manual and has some pitfalls we will go over. Let's take a look at how we might split another module from the main bundle: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- another-module.js -|- /node_modules -``` - -__another-module.js__ - -``` js -import _ from 'lodash'; - -console.log( - _.join(['Another', 'module', 'loaded!'], ' ') -); -``` - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - mode: 'development', - entry: { - index: './src/index.js', -+ another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -This will yield the following build result: - -``` bash -... - Asset Size Chunks Chunk Names -another.bundle.js 550 KiB another [emitted] another - index.bundle.js 550 KiB index [emitted] index -Entrypoint index = index.bundle.js -Entrypoint another = another.bundle.js -... -``` - -As mentioned there are some pitfalls to this approach: - -- If there are any duplicated modules between entry chunks they will be included in both bundles. -- It isn't as flexible and can't be used to dynamically split code with the core application logic. - -The first of these two points is definitely an issue for our example, as `lodash` is also imported within `./src/index.js` and will thus be duplicated in both bundles. Let's remove this duplication by using the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). - - -## Prevent Duplication - -The [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) allows us to extract common dependencies into an existing entry chunk or an entirely new chunk. Let's use this to de-duplicate the `lodash` dependency from the previous example: - -W> The `CommonsChunkPlugin` has been removed in webpack v4 legato. To learn how chunks are treated in the latest version, check out the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - mode: 'development', - entry: { - index: './src/index.js', - another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ optimization: { -+ splitChunks: { -+ chunks: 'all' -+ } -+ } - }; -``` - -With the [`optimization.splitChunks`](/plugins/split-chunks-plugin/#optimization-splitchunks) configuration option in place, we should now see the duplicate dependency removed from our `index.bundle.js` and `another.bundle.js`. The plugin should notice that we've separated `lodash` out to a separate chunk and remove the dead weight from our main bundle. Let's do an `npm run build` to see if it worked: - -``` bash -... - Asset Size Chunks Chunk Names - another.bundle.js 5.95 KiB another [emitted] another - index.bundle.js 5.89 KiB index [emitted] index -vendors~another~index.bundle.js 547 KiB vendors~another~index [emitted] vendors~another~index -Entrypoint index = vendors~another~index.bundle.js index.bundle.js -Entrypoint another = vendors~another~index.bundle.js another.bundle.js -... -``` - -Here are some other useful plugins and loaders provided by the community for splitting code: - -- [`mini-css-extract-plugin`](/plugins/mini-css-extract-plugin): Useful for splitting CSS out from the main application. -- [`bundle-loader`](/loaders/bundle-loader): Used to split code and lazy load the resulting bundles. -- [`promise-loader`](https://github.com/gaearon/promise-loader): Similar to the `bundle-loader` but uses promises. - - -## Dynamic Imports - -Two similar techniques are supported by webpack when it comes to dynamic code splitting. The first and recommended approach is to use the [`import()` syntax](/api/module-methods#import-) that conforms to the [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) for dynamic imports. The legacy, webpack-specific approach is to use [`require.ensure`](/api/module-methods#require-ensure). Let's try using the first of these two approaches... - -W> `import()` calls use [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -Before we start, let's remove the extra [`entry`](/concepts/entry-points/) and [`optimization.splitChunks`](/plugins/split-chunks-plugin) from our config as they won't be needed for this next demonstration: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - mode: 'development', - entry: { -+ index: './src/index.js' -- index: './src/index.js', -- another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', -+ chunkFilename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- optimization: { -- splitChunks: { -- chunks: 'all' -- } -- } - }; -``` - -Note the use of `chunkFilename`, which determines the name of non-entry chunk files. For more information on `chunkFilename`, see [output documentation](/configuration/output/#output-chunkfilename). We'll also update our project to remove the now unused files: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -- |- another-module.js -|- /node_modules -``` - -Now, instead of statically importing `lodash`, we'll use dynamic importing to separate a chunk: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -- -- function component() { -+ function getComponent() { -- var element = document.createElement('div'); -- -- // Lodash, now imported by this script -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => { -+ var element = document.createElement('div'); -+ -+ element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ -+ return element; -+ -+ }).catch(error => 'An error occurred while loading the component'); - } - -- document.body.appendChild(component()); -+ getComponent().then(component => { -+ document.body.appendChild(component); -+ }) -``` - -The reason we need `default` is since webpack 4, when importing a CommonJS module, the import will no longer resolve to the value of `module.exports`, it will instead create an artificial namespace object for the CommonJS module, for more information on the reason behind this, read [webpack 4: import() and CommonJs](https://medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655) - -Note the use of `webpackChunkName` in the comment. This will cause our separate bundle to be named `lodash.bundle.js` instead of just `[id].bundle.js`. For more information on `webpackChunkName` and the other available options, see the [`import()` documentation](/api/module-methods#import-). Let's run webpack to see `lodash` separated out to a separate bundle: - -``` bash -... - Asset Size Chunks Chunk Names - index.bundle.js 7.88 KiB index [emitted] index -vendors~lodash.bundle.js 547 KiB vendors~lodash [emitted] vendors~lodash -Entrypoint index = index.bundle.js -... -``` - -As `import()` returns a promise, it can be used with [`async` functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). However, this requires using a pre-processor like Babel and the [Syntax Dynamic Import Babel Plugin](https://babeljs.io/docs/plugins/syntax-dynamic-import/#installation). Here's how it would simplify the code: - -__src/index.js__ - -``` diff -- function getComponent() { -+ async function getComponent() { -- return import(/* webpackChunkName: "lodash" */ 'lodash').then({ default: _ } => { -- var element = document.createElement('div'); -- -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- -- return element; -- -- }).catch(error => 'An error occurred while loading the component'); -+ var element = document.createElement('div'); -+ const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash'); -+ -+ element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ -+ return element; - } - - getComponent().then(component => { - document.body.appendChild(component); - }); -``` - - -## Prefetching/Preloading modules - -webpack 4.6.0+ adds support for prefetching and preloading. - -Using these inline directives while declaring your imports allows webpack to output “Resource Hint” which tells the browser that for: - -- prefetch: resource is probably needed for some navigation in the future -- preload: resource might be needed during the current navigation - -Simple prefetch example can be having a `HomePage` component, which renders a `LoginButton` component which then on demand loads a `LoginModal` component after being clicked. - -__LoginButton.js__ - -```js -//... -import(/* webpackPrefetch: true */ 'LoginModal'); -``` - -This will result in `<link rel="prefetch" href="login-modal-chunk.js">` being appended in the head of the page, which will instruct the browser to prefetch in idle time the `login-modal-chunk.js` file. - -T> webpack will add the prefetch hint once the parent chunk has been loaded. - -Preload directive has a bunch of differences compared to prefetch: - -- A preloaded chunk starts loading in parallel to the parent chunk. A prefetched chunk starts after the parent chunk finishes loading. -- A preloaded chunk has medium priority and is instantly downloaded. A prefetched chunk is downloaded while browser is idle. -- A preloaded chunk should be instantly requested by the parent chunk. A prefetched chunk can be used anytime in the future. -- Browser support is different. - -Simple preload example can be having a `Component` which always depends on a big library that should be in a separate chunk. - -Let's imagine a component `ChartComponent` which needs huge `ChartingLibrary`. It displays a `LoadingIndicator` when rendered and instantly does an on demand import of `ChartingLibrary`: - -__ChartComponent.js__ - -```js -//... -import(/* webpackPreload: true */ 'ChartingLibrary'); -``` - -When a page which uses the `ChartComponent` is requested, the charting-library-chunk is also requested via `<link rel="preload">`. Assuming the page-chunk is smaller and finishes faster, the page will be displayed with a `LoadingIndicator`, until the already requested `charting-library-chunk` finishes. This will give a little load time boost since it only needs one round-trip instead of two. Especially in high-latency environments. - -T> Using webpackPreload incorrectly can actually hurt performance, so be careful when using it. - - -## Bundle Analysis - -Once you start splitting your code, it can be useful to analyze the output to check where modules have ended up. The [official analyze tool](https://github.com/webpack/analyse) is a good place to start. There are some other community-supported options out there as well: - -- [webpack-chart](https://alexkuz.github.io/webpack-chart/): Interactive pie chart for webpack stats. -- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/): Visualize and analyze your bundles to see which modules are taking up space and which might be duplicates. -- [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer): A plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap. -- [webpack bundle optimize helper](https://webpack.jakoblind.no/optimize): This tool will analyze your bundle and give you actionable suggestions on what to improve to reduce your bundle size. - -## Next Steps - -See [Lazy Loading](/guides/lazy-loading) for a more concrete example of how `import()` can be used in a real application and [Caching](/guides/caching) to learn how to split code more effectively. - - -# Lazy Loading - -T> This guide is a small follow-up to [Code Splitting](/guides/code-splitting). If you have not yet read through that guide, please do so now. - -Lazy, or "on demand", loading is a great way to optimize your site or application. This practice essentially involves splitting your code at logical breakpoints, and then loading it once the user has done something that requires, or will require, a new block of code. This speeds up the initial load of the application and lightens its overall weight as some blocks may never even be loaded. - - -## Example - -Let's take the example from [Code Splitting](/guides/code-splitting#dynamic-imports) and tweak it a bit to demonstrate this concept even more. The code there does cause a separate chunk, `lodash.bundle.js`, to be generated and technically "lazy-loads" it as soon as the script is run. The trouble is that no user interaction is required to load the bundle -- meaning that every time the page is loaded, the request will fire. This doesn't help us too much and will impact performance negatively. - -Let's try something different. We'll add an interaction to log some text to the console when the user clicks a button. However, we'll wait to load that code (`print.js`) until the interaction occurs for the first time. To do this we'll go back and rework the [final _Dynamic Imports_ example](/guides/code-splitting#dynamic-imports) from _Code Splitting_ and leave `lodash` in the main chunk. - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- print.js -|- /node_modules -``` - -__src/print.js__ - -``` js -console.log('The print.js module has loaded! See the network tab in dev tools...'); - -export default () => { - console.log('Button Clicked: Here\'s "some text"!'); -}; -``` - -__src/index.js__ - -``` diff -+ import _ from 'lodash'; -+ -- async function getComponent() { -+ function component() { - var element = document.createElement('div'); -- const _ = await import(/* webpackChunkName: "lodash" */ 'lodash'); -+ var button = document.createElement('button'); -+ var br = document.createElement('br'); - -+ button.innerHTML = 'Click me and look at the console!'; - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.appendChild(br); -+ element.appendChild(button); -+ -+ // Note that because a network request is involved, some indication -+ // of loading would need to be shown in a production-level site/app. -+ button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => { -+ var print = module.default; -+ -+ print(); -+ }); - - return element; - } - -- getComponent().then(component => { -- document.body.appendChild(component); -- }); -+ document.body.appendChild(component()); -``` - -W> Note that when using `import()` on ES6 modules you must reference the `.default` property as it's the actual `module` object that will be returned when the promise is resolved. - -Now let's run webpack and check out our new lazy-loading functionality: - -``` bash -... - Asset Size Chunks Chunk Names -print.bundle.js 417 bytes 0 [emitted] print -index.bundle.js 548 kB 1 [emitted] [big] index - index.html 189 bytes [emitted] -... -``` - - -## Frameworks - -Many frameworks and libraries have their own recommendations on how this should be accomplished within their methodologies. Here are a few examples: - -- React: [Code Splitting and Lazy Loading](https://reacttraining.com/react-router/web/guides/code-splitting) -- Vue: [Lazy Load in Vue using Webpack's code splitting](https://alexjoverm.github.io/2017/07/16/Lazy-load-in-Vue-using-Webpack-s-code-splitting/) -- AngularJS: [AngularJS + Webpack = lazyLoad](https://medium.com/@var_bin/angularjs-webpack-lazyload-bb7977f390dd) by [@var_bincom](https://twitter.com/var_bincom) - - -# Caching - -T> The examples in this guide stem from [getting started](/guides/getting-started), [output management](/guides/output-management) and [code splitting](/guides/code-splitting). - -So we're using webpack to bundle our modular application which yields a deployable `/dist` directory. Once the contents of `/dist` have been deployed to a server, clients (typically browsers) will hit that server to grab the site and its assets. The last step can be time consuming, which is why browsers use a technique called [caching](https://searchstorage.techtarget.com/definition/cache). This allows sites to load faster with less unnecessary network traffic, however it can also cause headaches when you need new code to be picked up. - -This guide focuses on the configuration needed to ensure files produced by webpack compilation can remain cached unless their contents has changed. - - -## Output Filenames - -A simple way to ensure the browser picks up changed files is by using `output.filename` [substitutions](/configuration/output#output-filename). The `[hash]` substitution can be used to include a build-specific hash in the filename, however it's even better to use the `[contenthash]` substitution which is the hash of the content of a file, which is different for each asset. - -Let's get our project set up using the example from [getting started](/guides/getting-started) with the `plugins` from [output management](/guides/output-management), so we don't have to deal with maintaining our `index.html` file manually: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -|- /node_modules -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ -- title: 'Output Management' -+ title: 'Caching' - }) - ], - output: { -- filename: 'bundle.js', -+ filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Running our build script, `npm run build`, with this configuration should produce the following output: - -``` bash -... - Asset Size Chunks Chunk Names -main.7e2c49a622975ebd9b7e.js 544 kB 0 [emitted] [big] main - index.html 197 bytes [emitted] -... -``` - -As you can see the bundle's name now reflects its content (via the hash). If we run another build without making any changes, we'd expect that filename to stay the same. However, if we were to run it again, we may find that this is not the case: - -``` bash -... - Asset Size Chunks Chunk Names -main.205199ab45963f6a62ec.js 544 kB 0 [emitted] [big] main - index.html 197 bytes [emitted] -... -``` - -This is because webpack includes certain boilerplate, specifically the runtime and manifest, in the entry chunk. - -W> Output may differ depending on your current webpack version. Newer versions may not have all the same issues with hashing as some older versions, but we still recommend the following steps to be safe. - -## Extracting Boilerplate - -As we learned in [code splitting](/guides/code-splitting), the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) can be used to split modules out into separate bundles. webpack provides an optimization feature which does split out runtime code into a separate chunk(s) according to the options provided, simply use [`optimization.runtimeChunk`](/configuration/optimization/#optimization-runtimechunk) set to `single` for creating one runtime bundle: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, -+ optimization: { -+ runtimeChunk: 'single' -+ } - }; -``` - -Let's run another build to see the extracted `runtime` bundle: - -``` bash -Hash: 82c9c385607b2150fab2 -Version: webpack 4.12.0 -Time: 3027ms - Asset Size Chunks Chunk Names -runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime - main.e81de2cf758ada72f306.js 69.5 KiB 1 [emitted] main - index.html 275 bytes [emitted] -[1] (webpack)/buildin/module.js 497 bytes {1} [built] -[2] (webpack)/buildin/global.js 489 bytes {1} [built] -[3] ./src/index.js 309 bytes {1} [built] - + 1 hidden module -``` - -It's also good practice to extract third-party libraries, such as `lodash` or `react`, to a separate `vendor` chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date. -This can be done by using the [`cacheGroups`](/plugins/split-chunks-plugin/#splitchunks-cachegroups) option of the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) demonstrated in [Example 2 of SplitChunksPlugin](/plugins/split-chunks-plugin/#split-chunks-example-2). Lets add `optimization.splitChunks` with `cacheGroups` with next params and build: - -__webpack.config.js__ - -``` diff - var path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - }), - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, - optimization: { -- runtimeChunk: 'single' -+ runtimeChunk: 'single', -+ splitChunks: { -+ cacheGroups: { -+ vendor: { -+ test: /[\\/]node_modules[\\/]/, -+ name: 'vendors', -+ chunks: 'all' -+ } -+ } -+ } - } - }; -``` - -Let's run another build to see our new `vendor` bundle: - -``` bash -... - Asset Size Chunks Chunk Names -runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime -vendors.a42c3ca0d742766d7a28.js 69.4 KiB 1 [emitted] vendors - main.abf44fedb7d11d4312d7.js 240 bytes 2 [emitted] main - index.html 353 bytes [emitted] -... -``` - -We can now see that our `main` bundle does not contain `vendor` code from `node_modules` directory and is down in size to `240 bytes`! - -## Module Identifiers - -Let's add another module, `print.js`, to our project: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- print.js -|- /node_modules -``` - -__print.js__ - -``` diff -+ export default function print(text) { -+ console.log(text); -+ }; -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import Print from './print'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.onclick = Print.bind(null, 'Hello webpack!'); - - return element; - } - - document.body.appendChild(component()); -``` - -Running another build, we would expect only our `main` bundle's hash to change, however... - -``` bash -... - Asset Size Chunks Chunk Names - vendor.a7561fb0e9a071baadb9.js 541 kB 0 [emitted] [big] vendor - main.b746e3eb72875af2caa9.js 1.22 kB 1 [emitted] main -manifest.1400d5af64fc1b7b3a45.js 5.85 kB 2 [emitted] manifest - index.html 352 bytes [emitted] -... -``` - -... we can see that all three have. This is because each [`module.id`](/api/module-variables#module-id-commonjs-) is incremented based on resolving order by default. Meaning when the order of resolving is changed, the IDs will be changed as well. So, to recap: - -- The `main` bundle changed because of its new content. -- The `vendor` bundle changed because its `module.id` was changed. -- And, the `manifest` bundle changed because it now contains a reference to a new module. - -The first and last are expected -- it's the `vendor` hash we want to fix. Luckily, there are two plugins we can use to resolve this issue. The first is the `NamedModulesPlugin`, which will use the path to the module rather than a numerical identifier. While this plugin is useful during development for more readable output, it does take a bit longer to run. The second option is the [`HashedModuleIdsPlugin`](/plugins/hashed-module-ids-plugin), which is recommended for production builds: - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const webpack = require('webpack'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - }), -+ new webpack.HashedModuleIdsPlugin() - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, - optimization: { - runtimeChunk: 'single', - splitChunks: { - cacheGroups: { - vendor: { - test: /[\\/]node_modules[\\/]/, - name: 'vendors', - chunks: 'all' - } - } - } - } - }; -``` - -Now, despite any new local dependencies, our `vendor` hash should stay consistent between builds: - -``` bash -... - Asset Size Chunks Chunk Names - main.216e852f60c8829c2289.js 340 bytes 0 [emitted] main -vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors -runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime - index.html 353 bytes [emitted] -Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.216e852f60c8829c2289.js -... -``` - -And let's modify our `src/index.js` to temporarily remove that extra dependency: - -__src/index.js__ - -``` diff - import _ from 'lodash'; -- import Print from './print'; -+ // import Print from './print'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- element.onclick = Print.bind(null, 'Hello webpack!'); -+ // element.onclick = Print.bind(null, 'Hello webpack!'); - - return element; - } - - document.body.appendChild(component()); -``` - -And finally run our build again: - -``` bash -... - Asset Size Chunks Chunk Names - main.ad717f2466ce655fff5c.js 274 bytes 0 [emitted] main -vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors -runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime - index.html 353 bytes [emitted] -Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.ad717f2466ce655fff5c.js -... -``` - -We can see that both builds yielded `55e79e5927a639d21a1b` in the `vendor` bundle's filename. - - -## Conclusion - -Caching gets messy. Plain and simple. However the walk-through above should give you a running start to deploying consistent, cacheable assets. See the _Further Reading_ section below to learn more. - - -# Authoring Libraries - -Aside from applications, webpack can also be used to bundle JavaScript libraries. The following guide is meant for library authors looking to streamline their bundling strategy. - - -## Authoring a Library - -Let's assume that you are writing a small library ,`webpack-numbers`, that allows users to convert the numbers 1 through 5 from their numeric representation to a textual one and vice-versa, e.g. 2 to 'two'. - -The basic project structure may look like this: - -__project__ - -``` diff -+ |- webpack.config.js -+ |- package.json -+ |- /src -+ |- index.js -+ |- ref.json -``` - -Initialize npm, install webpack and lodash: - -``` bash -npm init -y -npm install --save-dev webpack lodash -``` - -__src/ref.json__ - -```json -[ - { - "num": 1, - "word": "One" - }, - { - "num": 2, - "word": "Two" - }, - { - "num": 3, - "word": "Three" - }, - { - "num": 4, - "word": "Four" - }, - { - "num": 5, - "word": "Five" - }, - { - "num": 0, - "word": "Zero" - } -] -``` - -__src/index.js__ - -``` js -import _ from 'lodash'; -import numRef from './ref.json'; - -export function numToWord(num) { - return _.reduce(numRef, (accum, ref) => { - return ref.num === num ? ref.word : accum; - }, ''); -} - -export function wordToNum(word) { - return _.reduce(numRef, (accum, ref) => { - return ref.word === word && word.toLowerCase() ? ref.num : accum; - }, -1); -} -``` - -The usage specification for the library use will be as follows: - -- __ES2015 module import:__ - -``` js -import * as webpackNumbers from 'webpack-numbers'; -// ... -webpackNumbers.wordToNum('Two'); -``` - -- __CommonJS module require:__ - -``` js -var webpackNumbers = require('webpack-numbers'); -// ... -webpackNumbers.wordToNum('Two'); -``` - -- __AMD module require:__ - -``` js -require(['webpackNumbers'], function ( webpackNumbers) { - // ... - webpackNumbers.wordToNum('Two'); -}); -``` - -The consumer also can use the library by loading it via a script tag: - -``` html -<!doctype html> -<html> - ... - <script src="https://unpkg.com/webpack-numbers"></script> - <script> - // ... - // Global variable - webpackNumbers.wordToNum('Five') - // Property in the window object - window.webpackNumbers.wordToNum('Five') - // ... - </script> -</html> -``` - -Note that we can also configure it to expose the library in the following ways: - -- Property in the global object, for node. -- Property in the `this` object. - -For full library configuration and code please refer to [webpack-library-example](https://github.com/kalcifer/webpack-library-example). - - -## Base Configuration - -Now let's bundle this library in a way that will achieve the following goals: - -- Using `externals` to avoid bundling `lodash`, so the consumer is required to load it. -- Setting the library name as `webpack-numbers`. -- Exposing the library as a variable called `webpackNumbers`. -- Being able to access the library inside Node.js. - -Also, the consumer should be able to access the library the following ways: - -- ES2015 module. i.e. `import webpackNumbers from 'webpack-numbers'`. -- CommonJS module. i.e. `require('webpack-numbers')`. -- Global variable when included through `script` tag. - -We can start with this basic webpack configuration: - -__webpack.config.js__ - -``` js -var path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js' - } -}; -``` - - -## Externalize Lodash - -Now, if you run `webpack`, you will find that a largish bundle is created. If you inspect the file, you'll see that lodash has been bundled along with your code. In this case, we'd prefer to treat `lodash` as a `peerDependency`. Meaning that the consumer should already have `lodash` installed. Hence you would want to give up control of this external library to the consumer of your library. - -This can be done using the `externals` configuration: - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js' -- } -+ }, -+ externals: { -+ lodash: { -+ commonjs: 'lodash', -+ commonjs2: 'lodash', -+ amd: 'lodash', -+ root: '_' -+ } -+ } - }; -``` - -This means that your library expects a dependency named `lodash` to be available in the consumer's environment. - -T> Note that if you only plan on using your library as a dependency in another webpack bundle, you may specify `externals` as an array. - - -## External Limitations - -For libraries that use several files from a dependency: - -``` js -import A from 'library/one'; -import B from 'library/two'; - -// ... -``` - -You won't be able to exclude them from bundle by specifying `library` in the externals. You'll either need to exclude them one by one or by using a regular expression. - -``` js -module.exports = { - //... - externals: [ - 'library/one', - 'library/two', - // Everything that starts with "library/" - /^library\/.+$/ - ] -}; -``` - - -## Expose the Library - -For widespread use of the library, we would like it to be compatible in different environments, i.e. CommonJS, AMD, Node.js and as a global variable. To make your library available for consumption, add the `library` property inside `output`: - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), -- filename: 'webpack-numbers.js' -+ filename: 'webpack-numbers.js', -+ library: 'webpackNumbers' - }, - externals: { - lodash: { - commonjs: 'lodash', - commonjs2: 'lodash', - amd: 'lodash', - root: '_' - } - } - }; -``` - -T> Note that the `library` setup is tied to the `entry` configuration. For most libraries, specifying a single entry point is sufficient. While [multi-part libraries](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) are possible, it is simpler to expose partial exports through an [index script](https://stackoverflow.com/questions/34072598/es6-exporting-importing-in-index-file) that serves as a single entry point. Using an `array` as an `entry` point for a library is __not recommended__. - -This exposes your library bundle available as a global variable named `webpackNumbers` when imported. To make the library compatible with other environments, add `libraryTarget` property to the config. This will add the different options about how the library can be exposed. - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js', -- library: 'webpackNumbers' -+ library: 'webpackNumbers', -+ libraryTarget: 'umd' - }, - externals: { - lodash: { - commonjs: 'lodash', - commonjs2: 'lodash', - amd: 'lodash', - root: '_' - } - } - }; -``` - -You can expose the library in the following ways: - -- Variable: as a global variable made available by a `script` tag (`libraryTarget:'var'`). -- This: available through the `this` object (`libraryTarget:'this'`). -- Window: available trough the `window` object, in the browser (`libraryTarget:'window'`). -- UMD: available after AMD or CommonJS `require` (`libraryTarget:'umd'`). - -If `library` is set and `libraryTarget` is not, `libraryTarget` defaults to `var` as specified in the [output configuration documentation](/configuration/output). See [`output.libraryTarget`](/configuration/output#output-librarytarget) there for a detailed list of all available options. - -W> With webpack 3.5.5, using `libraryTarget: { root:'_' }` doesn't work properly (as stated in [issue 4824](https://github.com/webpack/webpack/issues/4824)). However, you can set `libraryTarget: { var: '_' }` to expect the library as a global variable. - - -### Final Steps - -Optimize your output for production by following the steps in the [production guide](/guides/production). Let's also add the path to your generated bundle as the package's `main` field in with our `package.json` - -__package.json__ - -``` json -{ - ... - "main": "dist/webpack-numbers.js", - ... -} -``` - -Or, to add as standard module as per [this guide](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage): - -``` json -{ - ... - "module": "src/index.js", - ... -} -``` - -The key `main` refers to the [standard from `package.json`](https://docs.npmjs.com/files/package.json#main), and `module` to [a](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md) [proposal](https://github.com/rollup/rollup/wiki/pkg.module) to allow the JavaScript ecosystem upgrade to use ES2015 modules without breaking backwards compatibility. - -W> The `module` property should point to a script that utilizes ES2015 module syntax but no other syntax features that aren't yet supported by browsers or node. This enables webpack to parse the module syntax itself, allowing for lighter bundles via [tree shaking](https://webpack.js.org/guides/tree-shaking/) if users are only consuming certain parts of the library. - -Now you can [publish it as an npm package](https://docs.npmjs.com/getting-started/publishing-npm-packages) and find it at [unpkg.com](https://unpkg.com/#/) to distribute it to your users. - -T> To expose stylesheets associated with your library, the [`ExtractTextPlugin`](/plugins/extract-text-webpack-plugin) should be used. Users can then consume and load these as they would any other stylesheet. - - -# Shimming - -The `webpack` compiler can understand modules written as ES2015 modules, CommonJS or AMD. However, some third party libraries may expect global dependencies (e.g. `$` for `jQuery`). The libraries might also create globals which need to be exported. These "broken modules" are one instance where _shimming_ comes into play. - -W> __We don't recommend using globals!__ The whole concept behind webpack is to allow more modular front-end development. This means writing isolated modules that are well contained and do not rely on hidden dependencies (e.g. globals). Please use these features only when necessary. - -Another instance where _shimming_ can be useful is when you want to [polyfill](https://en.wikipedia.org/wiki/Polyfill) browser functionality to support more users. In this case, you may only want to deliver those polyfills to the browsers that need patching (i.e. load them on demand). - -The following article will walk through both of these use cases. - -T> For simplicity, this guide stems from the examples in [Getting Started](/guides/getting-started). Please make sure you are familiar with the setup there before moving on. - - -## Shimming Globals - -Let's start with the first use case of shimming global variables. Before we do anything let's take another look at our project: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -|- /node_modules -``` - -Remember that `lodash` package we were using? For demonstration purposes, let's say we wanted to instead provide this as a global throughout our application. To do this, we can use the `ProvidePlugin`. - -The [`ProvidePlugin`](/plugins/provide-plugin) makes a package available as a variable in every module compiled through webpack. If webpack sees that variable used, it will include the given package in the final bundle. Let's go ahead by removing the `import` statement for `lodash` and instead providing it via the plugin: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -- - function component() { - var element = document.createElement('div'); - -- // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') -- } -+ }, -+ plugins: [ -+ new webpack.ProvidePlugin({ -+ _: 'lodash' -+ }) -+ ] - }; -``` - -What we've essentially done here is tell webpack... - -> If you encounter at least one instance of the variable `_`, include the `lodash` package and provide it to the modules that need it. - -If we run a build, we should still see the same output: - -``` bash -... - Asset Size Chunks Chunk Names -bundle.js 544 kB 0 [emitted] [big] main -... -``` - -We can also use the `ProvidePlugin` to expose a single export of a module by configuring it with an "array path" (e.g. `[module, child, ...children?]`). So let's imagine we only wanted to provide the `join` method from `lodash` wherever it's invoked: - -__src/index.js__ - -``` diff - function component() { - var element = document.createElement('div'); - -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - plugins: [ - new webpack.ProvidePlugin({ -- _: 'lodash' -+ join: ['lodash', 'join'] - }) - ] - }; -``` - -This would go nicely with [Tree Shaking](/guides/tree-shaking) as the rest of the `lodash` library should get dropped. - - -## Granular Shimming - -Some legacy modules rely on `this` being the `window` object. Let's update our `index.js` so this is the case: - -``` diff - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); -+ -+ // Assume we are in the context of `window` -+ this.alert('Hmmm, this probably isn\'t a great idea...') - - return element; - } - - document.body.appendChild(component()); -``` - -This becomes a problem when the module is executed in a CommonJS context where `this` is equal to `module.exports`. In this case you can override `this` using the [`imports-loader`](/loaders/imports-loader/): - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ module: { -+ rules: [ -+ { -+ test: require.resolve('index.js'), -+ use: 'imports-loader?this=>window' -+ } -+ ] -+ }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - - -## Global Exports - -Let's say a library creates a global variable that it expects its consumers to use. We can add a small module to our setup to demonstrate this: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js -+ |- globals.js - |- /node_modules -``` - -__src/globals.js__ - -``` js -var file = 'blah.txt'; -var helpers = { - test: function() { console.log('test something'); }, - parse: function() { console.log('parse something'); } -}; -``` - -Now, while you'd likely never do this in your own source code, you may encounter a dated library you'd like to use that contains similar code to what's shown above. In this case, we can use [`exports-loader`](/loaders/exports-loader/), to export that global variable as a normal module export. For instance, in order to export `file` as `file` and `helpers.parse` as `parse`: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: require.resolve('index.js'), - use: 'imports-loader?this=>window' -- } -+ }, -+ { -+ test: require.resolve('globals.js'), -+ use: 'exports-loader?file,parse=helpers.parse' -+ } - ] - }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - -Now from within our entry script (i.e. `src/index.js`), we could `import { file, parse } from './globals.js';` and all should work smoothly. - - -## Loading Polyfills - -Almost everything we've discussed thus far has been in relation to handling legacy packages. Let's move on to our second topic: __polyfills__. - -There's a lot of ways to load polyfills. For example, to include the [`babel-polyfill`](https://babeljs.io/docs/usage/polyfill/) we might simply: - -``` bash -npm install --save babel-polyfill -``` - -and `import` it so as to include it in our main bundle: - -__src/index.js__ - -``` diff -+ import 'babel-polyfill'; -+ - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -T> Note that we aren't binding the `import` to a variable. This is because polyfills simply run on their own, prior to the rest of the code base, allowing us to then assume certain native functionality exists. - -Now while this is one approach, __including polyfills in the main bundle is not recommended__ because this penalizes modern browsers users by making them download a bigger file with unneeded scripts. - -Let's move our `import` to a new file and add the [`whatwg-fetch`](https://github.com/github/fetch) polyfill: - -``` bash -npm install --save whatwg-fetch -``` - -__src/index.js__ - -``` diff -- import 'babel-polyfill'; -- - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js - |- globals.js -+ |- polyfills.js - |- /node_modules -``` - -__src/polyfills.js__ - -```javascript -import 'babel-polyfill'; -import 'whatwg-fetch'; -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { -- entry: './src/index.js', -+ entry: { -+ polyfills: './src/polyfills.js', -+ index: './src/index.js' -+ }, - output: { -- filename: 'bundle.js', -+ filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: require.resolve('index.js'), - use: 'imports-loader?this=>window' - }, - { - test: require.resolve('globals.js'), - use: 'exports-loader?file,parse=helpers.parse' - } - ] - }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - -With that in place, we can add the logic to conditionally load our new `polyfills.bundle.js` file. How you make this decision depends on the technologies and browsers you need to support. We'll just do some simple testing to determine whether our polyfills are needed: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> - <title>Getting Started</title> -+ <script> -+ var modernBrowser = ( -+ 'fetch' in window && -+ 'assign' in Object -+ ); -+ -+ if ( !modernBrowser ) { -+ var scriptElement = document.createElement('script'); -+ -+ scriptElement.async = false; -+ scriptElement.src = '/polyfills.bundle.js'; -+ document.head.appendChild(scriptElement); -+ } -+ </script> - </head> - <body> - <script src="index.bundle.js"></script> - </body> - </html> -``` - -Now we can `fetch` some data within our entry script: - -__src/index.js__ - -``` diff - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -+ -+ fetch('https://jsonplaceholder.typicode.com/users') -+ .then(response => response.json()) -+ .then(json => { -+ console.log('We retrieved some data! AND we\'re confident it will work on a variety of browser distributions.') -+ console.log(json) -+ }) -+ .catch(error => console.error('Something went wrong when fetching this data: ', error)) -``` - -If we run our build, another `polyfills.bundle.js` file will be emitted and everything should still run smoothly in the browser. Note that this set up could likely be improved upon but it should give you a good idea of how you can provide polyfills only to the users that actually need them. - - -## Further Optimizations - -The `babel-preset-env` package uses [browserslist](https://github.com/browserslist/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the [`useBuiltIns`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins) option, `false` by default, which converts your global `babel-polyfill` import to a more granular feature by feature `import` pattern: - -``` js -import 'core-js/modules/es7.string.pad-start'; -import 'core-js/modules/es7.string.pad-end'; -import 'core-js/modules/web.timers'; -import 'core-js/modules/web.immediate'; -import 'core-js/modules/web.dom.iterable'; -``` - -See [the repository](https://github.com/babel/babel-preset-env) for more information. - - -## Node Built-Ins - -Node built-ins, like `process`, can be polyfilled right directly from your configuration file without the use of any special loaders or plugins. See the [node configuration page](/configuration/node) for more information and examples. - - -## Other Utilities - -There are a few other tools that can help when dealing with legacy modules. - -The [`script-loader`](/loaders/script-loader/) evaluates code in the global context, similar to inclusion via a `script` tag. In this mode, every normal library should work. `require`, `module`, etc. are undefined. - -W> When using the `script-loader`, the module is added as a string to the bundle. It is not minimized by `webpack`, so use a minimized version. There is also no `devtool` support for libraries added by this loader. - -When there is no AMD/CommonJS version of the module and you want to include the `dist`, you can flag this module in [`noParse`](/configuration/module/#module-noparse). This will cause webpack to include the module without parsing it or resolving `require()` and `import` statements. This practice is also used to improve the build performance. - -W> Any feature requiring the AST, like the `ProvidePlugin`, will not work. - -Lastly, there are some modules that support multiple [module styles](/concepts/modules); e.g. a combination of AMD, CommonJS, and legacy. In most of these cases, they first check for `define` and then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by setting `define=>false` via the [`imports-loader`](/loaders/imports-loader/). - - -# Progressive Web Application - -T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. - -Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications. There are many things that can contribute to that. Of these, the most significant is the ability for an app to be able to function when __offline__. This is achieved through the use of a web technology called [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers/). - -This section will focus on adding an offline experience to our app. We'll achieve this using a Google project called [Workbox](https://github.com/GoogleChrome/workbox) which provides tools that help make offline support for web apps easier to setup. - - -## We Don't Work Offline Now - -So far, we've been viewing the output by going directly to the local file system. Typically though, a real user accesses a web app over a network; their browser talking to a __server__ which will serve up the required assets (e.g. `.html`, `.js`, and `.css` files). - -So let's test what the current experience is like using a simple server. Let's use the [http-server](https://www.npmjs.com/package/http-server) package: `npm install http-server --save-dev`. We'll also amend the `scripts` section of our `package.json` to add in a `start` script: - -__package.json__ - -``` diff -{ - ... - "scripts": { -- "build": "webpack" -+ "build": "webpack", -+ "start": "http-server dist" - }, - ... -} -``` - -If you haven't previously done so, run the command `npm run build` to build your project. Then run the command `npm start`. This should produce the following output: - -``` bash -> http-server dist - -Starting up http-server, serving dist -Available on: - http://xx.x.x.x:8080 - http://127.0.0.1:8080 - http://xxx.xxx.x.x:8080 -Hit CTRL-C to stop the server -``` - -If you open your browser to `http://localhost:8080` (i.e. `http://127.0.0.1`) you should see your webpack application being served from the `dist` directory. If you stop the server and refresh, the webpack application is no longer available. - -This is what we aim to change. Once we reach the end of this module we should be able to stop the server, hit refresh and still see our application. - - -## Adding Workbox - -Let's add the Workbox webpack plugin and adjust the `webpack.config.js` file: - -``` bash -npm install workbox-webpack-plugin --save-dev -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const WorkboxPlugin = require('workbox-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ -- title: 'Output Management' -+ title: 'Progressive Web Application' -- }) -+ }), -+ new WorkboxPlugin.GenerateSW({ -+ // these options encourage the ServiceWorkers to get in there fast -+ // and not allow any straggling "old" SWs to hang around -+ clientsClaim: true, -+ skipWaiting: true -+ }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -With that in place, let's see what happens when we do an `npm run build`: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 545 kB 0, 1 [emitted] [big] app - print.bundle.js 2.74 kB 1 [emitted] print - index.html 254 bytes [emitted] -precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 268 bytes [emitted] - service-worker.js 1 kB [emitted] -... -``` - -As you can see, we now have 2 extra files being generated; `service-worker.js` and the more verbose `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js`. `service-worker.js` is the Service Worker file and `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js` is a file that `service-worker.js` requires so it can run. Your own generated files will likely be different; but you should have an `service-worker.js` file there. - -So we're now at the happy point of having produced a Service Worker. What's next? - - -## Registering Our Service Worker - -Let's allow our Service Worker to come out and play by registering it. We'll do that by adding the registration code below: - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - -+ if ('serviceWorker' in navigator) { -+ window.addEventListener('load', () => { -+ navigator.serviceWorker.register('/service-worker.js').then(registration => { -+ console.log('SW registered: ', registration); -+ }).catch(registrationError => { -+ console.log('SW registration failed: ', registrationError); -+ }); -+ }); -+ } -``` - -Once more `npm run build` to build a version of the app including the registration code. Then serve it with `npm start`. Navigate to `http://localhost:8080` and take a look at the console. Somewhere in there you should see: - -``` bash -SW registered -``` - -Now to test it. Stop your server and refresh your page. If your browser supports Service Workers then you should still be looking at your application. However, it has been served up by your Service Worker and __not__ by the server. - - -## Conclusion - -You have built an offline app using the Workbox project. You've started the journey of turning your web app into a PWA. You may now want to think about taking things further. A good resource to help you with that can be found [here](https://developers.google.com/web/progressive-web-apps/). - - -# TypeScript - -T> This guide stems from the [_Getting Started_](/guides/getting-started/) guide. - -[TypeScript](https://www.typescriptlang.org) is a typed superset of JavaScript that compiles to plain JavaScript. In this guide we will learn how to integrate TypeScript with webpack. - - -## Basic Setup - -First install the TypeScript compiler and loader by running: - -``` bash -npm install --save-dev typescript ts-loader -``` - -Now we'll modify the directory structure & the configuration files: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- tsconfig.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src - |- index.js -+ |- index.ts - |- /node_modules -``` - -__tsconfig.json__ - -Let's set up a simple configuration to support JSX and compile TypeScript down to ES5... - -``` json -{ - "compilerOptions": { - "outDir": "./dist/", - "noImplicitAny": true, - "module": "es6", - "target": "es5", - "jsx": "react", - "allowJs": true - } -} -``` - -See [TypeScript's documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) to learn more about `tsconfig.json` configuration options. - -To learn more about webpack configuration, see the [configuration concepts](/concepts/configuration/). - -Now let's configure webpack to handle TypeScript: - -__webpack.config.js__ - -``` js -const path = require('path'); - -module.exports = { - entry: './src/index.ts', - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: [ '.tsx', '.ts', '.js' ] - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -This will direct webpack to _enter_ through `./index.ts`, _load_ all `.ts` and `.tsx` files through the `ts-loader`, and _output_ a `bundle.js` file in our current directory. - - -## Loader - -[`ts-loader`](https://github.com/TypeStrong/ts-loader) - -We use `ts-loader` in this guide as it makes enabling additional webpack features, such as importing other web assets, a bit easier. - - -## Source Maps - -To learn more about source maps, see the [development guide](/guides/development). - -To enable source maps, we must configure TypeScript to output inline source maps to our compiled JavaScript files. The following line must be added to our TypeScript configuration: - -__tsconfig.json__ - -``` diff - { - "compilerOptions": { - "outDir": "./dist/", -+ "sourceMap": true, - "noImplicitAny": true, - "module": "commonjs", - "target": "es5", - "jsx": "react", - "allowJs": true - } - } -``` - -Now we need to tell webpack to extract these source maps and include in our final bundle: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.ts', -+ devtool: 'inline-source-map', - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: [ '.tsx', '.ts', '.js' ] - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -See the [devtool documentation](/configuration/devtool/) for more information. - - -## Using Third Party Libraries - -When installing third party libraries from npm, it is important to remember to install the typing definition for that library. These definitions can be found at [TypeSearch](http://microsoft.github.io/TypeSearch/). - -For example if we want to install lodash we can run the following command to get the typings for it: - -``` bash -npm install --save-dev @types/lodash -``` - -For more information see [this blog post](https://blogs.msdn.microsoft.com/typescript/2016/06/15/the-future-of-declaration-files/). - - -## Importing Other Assets - -To use non-code assets with TypeScript, we need to defer the type for these imports. This requires a `custom.d.ts` file which signifies custom definitions for TypeScript in our project. Let's set up a declaration for `.svg` files: - -__custom.d.ts__ - -```typescript -declare module "*.svg" { - const content: any; - export default content; -} -``` - -Here we declare a new module for SVGs by specifying any import that ends in `.svg` and defining the module's `content` as `any`. We could be more explicit about it being a url by defining the type as string. The same concept applies to other assets including CSS, SCSS, JSON and more. - - -## Build Performance - -W> This may degrade build performance. - -See the [Build Performance](/guides/build-performance/) guide on build tooling. - - -# Environment Variables - -To disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production) you may use environment variables. - -The webpack command line [environment option](/api/cli/#environment-options) `--env` allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your `webpack.config.js`. For example, `--env.production` or `--env.NODE_ENV=local` (`NODE_ENV` is conventionally used to define the environment type, see [here](https://dzone.com/articles/what-you-should-know-about-node-env).) - -```bash -webpack --env.NODE_ENV=local --env.production --progress -``` - -T> Setting up your `env` variable without assignment, `--env.production` sets `--env.production` to `true` by default. There are also other syntaxes that you can use. See the [webpack CLI](/api/cli/#environment-options) documentation for more information. - -There is one change that you will have to make to your webpack config. Typically, `module.exports` points to the configuration object. To use the `env` variable, you must convert `module.exports` to a function: - -__webpack.config.js__ - -``` js -const path = require('path'); - -module.exports = env => { - // Use env.<YOUR VARIABLE> here: - console.log('NODE_ENV: ', env.NODE_ENV); // 'local' - console.log('Production: ', env.production); // true - - return { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -}; -``` - - -# Build Performance - -This guide contains some useful tips for improving build/compilation performance. - ---- - -## General - -The following best practices should help, whether you're running build scripts in [development](/guides/development) or [production](/guides/production). - - -### Stay Up to Date - -Use the latest webpack version. We are always making performance improvements. The latest stable version of webpack is: - -[](https://github.com/webpack/webpack/releases) - -Staying up-to-date with __Node.js__ can also help with performance. On top of this, keeping your package manager (e.g. `npm` or `yarn`) up-to-date can also help. Newer versions create more efficient module trees and increase resolving speed. - - -### Loaders - -Apply loaders to the minimal number of modules necessary. Instead of: - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - loader: 'babel-loader' - } - ] - } -}; -``` - -Use the `include` field to only apply the loader modules that actually need to be transformed by it: - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - include: path.resolve(__dirname, 'src'), - loader: 'babel-loader' - } - ] - } -}; -``` - - -### Bootstrap - -Each additional loader/plugin has a bootup time. Try to use as few tools as possible. - - -### Resolving - -The following steps can increase resolving speed: - -- Minimize the number of items in `resolve.modules`, `resolve.extensions`, `resolve.mainFiles`, `resolve.descriptionFiles`, as they increase the number of filesystem calls. -- Set `resolve.symlinks: false` if you don't use symlinks (e.g. `npm link` or `yarn link`). -- Set `resolve.cacheWithContext: false` if you use custom resolving plugins, that are not context specific. - - -### Dlls - -Use the `DllPlugin` to move code that is changed less often into a separate compilation. This will improve the application's compilation speed, although it does increase complexity of the build process. - - -### Smaller = Faster - -Decrease the total size of the compilation to increase build performance. Try to keep chunks small. - -- Use fewer/smaller libraries. -- Use the `CommonsChunkPlugin` in Multi-Page Applications. -- Use the `CommonsChunkPlugin` in `async` mode in Multi-Page Applications. -- Remove unused code. -- Only compile the part of the code you are currently developing on. - - -### Worker Pool - -The `thread-loader` can be used to offload expensive loaders to a worker pool. - -W> Don't use too many workers, as there is a boot overhead for the Node.js runtime and the loader. Minimize the module transfers between worker and main process. IPC is expensive. - - -### Persistent cache - -Enable persistent caching with the `cache-loader`. Clear cache directory on `"postinstall"` in `package.json`. - - -### Custom plugins/loaders - -Profile them to not introduce a performance problem here. - ---- - - -## Development - -The following steps are especially useful in _development_. - - -### Incremental Builds - -Use webpack's watch mode. Don't use other tools to watch your files and invoke webpack. The built-in watch mode will keep track of timestamps and passes this information to the compilation for cache invalidation. - -In some setups, watching falls back to polling mode. With many watched files, this can cause a lot of CPU load. In these cases, you can increase the polling interval with `watchOptions.poll`. - - -### Compile in Memory - -The following utilities improve performance by compiling and serving assets in memory rather than writing to disk: - -- `webpack-dev-server` -- `webpack-hot-middleware` -- `webpack-dev-middleware` - -### stats.toJson speed - -webpack 4 outputs a large amount of data with its `stats.toJson()` by default. Avoid retrieving portions of the `stats` object unless necessary in the incremental step. `webpack-dev-server` after v3.1.3 contained a substantial performance fix to minimize the amount of data retrieved from the `stats` object per incremental build step. - -### Devtool - -Be aware of the performance differences of the different `devtool` settings. - -- `"eval"` has the best performance, but doesn't assist you for transpiled code. -- The `cheap-source-map` variants are more performant, if you can live with the slightly worse mapping quality. -- Use a `eval-source-map` variant for incremental builds. - -=> In most cases, `cheap-module-eval-source-map` is the best option. - - -### Avoid Production Specific Tooling - -Certain utilities, plugins, and loaders only make sense when building for production. For example, it usually doesn't make sense to minify and mangle your code with the `TerserPlugin` while in development. These tools should typically be excluded in development: - -- `TerserPlugin` -- `ExtractTextPlugin` -- `[hash]`/`[chunkhash]` -- `AggressiveSplittingPlugin` -- `AggressiveMergingPlugin` -- `ModuleConcatenationPlugin` - - -### Minimal Entry Chunk - -webpack only emits updated chunks to the filesystem. For some configuration options, (HMR, `[name]`/`[chunkhash]` in `output.chunkFilename`, `[hash]`) the entry chunk is invalidated in addition to the changed chunks. - -Make sure the entry chunk is cheap to emit by keeping it small. The following code block extracts a chunk containing only the runtime with _all other chunks as children_: - -```js -new CommonsChunkPlugin({ - name: 'manifest', - minChunks: Infinity -}); -``` - -### Avoid Extra Optimization Steps - -webpack does extra algorithmic work to optimize the output for size and load performance. These optimizations are performant for smaller codebases, but can be costly in larger ones: - -```js -module.exports = { - // ... - optimization: { - removeAvailableModules: false, - removeEmptyChunks: false, - splitChunks: false, - } -}; -``` - -### Output Without Path Info - -webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Turn this off in the `options.output.pathinfo` setting: - -```js -module.exports = { - // ... - output: { - pathinfo: false - } -}; -``` - -### Node.js Version - -There has been a [performance regression](https://github.com/nodejs/node/issues/19769) in the latest stable versions of Node.js and its ES2015 `Map` and `Set` implementations. A fix has been merged into master, but a release has yet to be made. In the meantime, to get the most out of incremental build speeds, try to stick with version 8.9.x (the problem exists between 8.9.10 - 9.11.1). webpack has moved to using those ES2015 data structures liberally, and it will improve the initial build times as well. - -### TypeScript Loader - -Recently, `ts-loader` has started to consume the internal TypeScript watch mode APIs which dramatically decreases the number of modules to be rebuilt on each iteration. This `experimentalWatchApi` shares the same logic as the normal TypeScript watch mode itself and is quite stable for development use. Turn on `transpileOnly`, as well, for even faster incremental builds. - -```js -module.exports = { - // ... - test: /\.tsx?$/, - use: [ - { - loader: 'ts-loader', - options: { - transpileOnly: true, - experimentalWatchApi: true, - }, - }, - ], -}; -``` - -Note: the `ts-loader` documentation suggests the use of `cache-loader`, but this actually slows the incremental builds down with disk writes. - -To gain typechecking again, use the [`ForkTsCheckerWebpackPlugin`](https://www.npmjs.com/package/fork-ts-checker-webpack-plugin). - -There is a [full example](https://github.com/TypeStrong/ts-loader/tree/master/examples/fast-incremental-builds) on the ts-loader github repository. - ---- - - -## Production - -The following steps are especially useful in _production_. - -W> __Don't sacrifice the quality of your application for small performance gains!__ Keep in mind that optimization quality is, in most cases, more important than build performance. - - -### Multiple Compilations - -When using multiple compilations, the following tools can help: - -- [`parallel-webpack`](https://github.com/trivago/parallel-webpack): It allows for compilation in a worker pool. -- `cache-loader`: The cache can be shared between multiple compilations. - - -### Source Maps - -Source maps are really expensive. Do you really need them? - ---- - - -## Specific Tooling Issues - -The following tools have certain problems that can degrade build performance: - - -### Babel - -- Minimize the number of preset/plugins - - -### TypeScript - -- Use the `fork-ts-checker-webpack-plugin` for typechecking in a separate process. -- Configure loaders to skip typechecking. -- Use the `ts-loader` in `happyPackMode: true` / `transpileOnly: true`. - - -### Sass - -- `node-sass` has a bug which blocks threads from the Node.js thread pool. When using it with the `thread-loader` set `workerParallelJobs: 2`. - - -# Content Security Policies - -Webpack is capable of adding `nonce` to all scripts that it loads. To activate the feature set a `__webpack_nonce__` variable needs to be included in your entry script. A unique hash based nonce should be generated and provided for each unique page view this is why `__webpack_nonce__` is specified in the entry file and not in the configuration. Please note that `nonce` should always be a base64-encoded string. - - -## Examples - -In the entry file: - -``` js -// ... -__webpack_nonce__ = 'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM='; -// ... -``` - - -## Enabling CSP - -Please note that CSPs are not enabled by default. A corresponding header `Content-Security-Policy` or meta tag `<meta http-equiv="Content-Security-Policy" ...>` needs to be sent with the document to instruct the browser to enable the CSP. Here's an example of what a CSP header including a CDN white-listed URL might look like: - -``` http -Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; -``` - -For more information on CSP and `nonce` attribute, please refer to __Further Reading__ section at the bottom of this page. - - -# Development - Vagrant - -If you have a more advanced project and use [Vagrant](https://www.vagrantup.com/) to run your development environment in a Virtual Machine, you'll often want to also run webpack in the VM. - -## Configuring the Project - -To start, make sure that the `Vagrantfile` has a static IP; - -```ruby -Vagrant.configure("2") do |config| - config.vm.network :private_network, ip: "10.10.10.61" -end -``` - -Next, install webpack and webpack-dev-server in your project; - -```bash -npm install --save-dev webpack webpack-dev-server -``` - -Make sure to have a `webpack.config.js` file. If you haven't already, use this as a minimal example to get started: - -```js -module.exports = { - context: __dirname, - entry: './app.js' -}; -``` - -And create a `index.html` file. The script tag should point to your bundle. If `output.filename` is not specified in the config, this will be `bundle.js`. - -```html -<!doctype html> -<html> - <head> - <script src="/bundle.js" charset="utf-8"></script> - </head> - <body> - <h2>Heey!</h2> - </body> -</html> -``` - -Note that you also need to create an `app.js` file. - -## Running the Server - -Now, let's run the server: - -```bash -webpack-dev-server --host 0.0.0.0 --public 10.10.10.61:8080 --watch-poll -``` - -By default the server will only be accessible from localhost. We'll be accessing it from our host PC, so we need to change `--host` to allow this. - -webpack-dev-server will include a script in your bundle that connects to a WebSocket to reload when a change in any of your files occurs. -The `--public` flag makes sure the script knows where to look for the WebSocket. The server will use port `8080` by default, so we should also specify that here. - -`--watch-poll` makes sure that webpack can detect changes in your files. By default webpack listens to events triggered by the filesystem, but VirtualBox has many problems with this. - -The server should be accessible on `http://10.10.10.61:8080` now. If you make a change in `app.js`, it should live reload. - -## Advanced Usage with nginx - -To mimic a more production-like environment, it is also possible to proxy the webpack-dev-server with nginx. - -In your nginx config file, add the following: - -```nginx -server { - location / { - proxy_pass http://127.0.0.1:8080; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - error_page 502 @start-webpack-dev-server; - } - - location @start-webpack-dev-server { - default_type text/plain; - return 502 "Please start the webpack-dev-server first."; - } -} -``` - -The `proxy_set_header` lines are important, because they allow the WebSockets to work correctly. - -The command to start webpack-dev-server can then be changed to this: - -```bash -webpack-dev-server --public 10.10.10.61 --watch-poll -``` - -This makes the server only accessible on `127.0.0.1`, which is fine, because nginx takes care of making it available on your host PC. - -## Conclusion - -We made the Vagrant box accessible from a static IP, and then made webpack-dev-server publicly accessible so it is reachable from a browser. We then tackled a common problem that VirtualBox doesn't send out filesystem events, causing the server to not reload on file changes. - - -# Dependency Management - -> es6 modules - -> commonjs - -> amd - - -## require with expression - -A context is created if your request contains expressions, so the __exact__ module is not known on compile time. - -Example: - -```javascript -require('./template/' + name + '.ejs'); -``` - -webpack parses the `require()` call and extracts some information: - -```code -Directory: ./template -Regular expression: /^.*\.ejs$/ -``` - -__context module__ - -A context module is generated. It contains references to __all modules in that directory__ that can be required with a request matching the regular expression. The context module contains a map which translates requests to module ids. - -Example: - -```json -{ - "./table.ejs": 42, - "./table-row.ejs": 43, - "./directory/folder.ejs": 44 -} -``` - -The context module also contains some runtime logic to access the map. - -This means dynamic requires are supported but will cause all possible modules to be included in the bundle. - - -## `require.context` - -You can create your own context with the `require.context()` function. - -It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched -too, and a regular expression to match files against. - -webpack parses for `require.context()` in the code while building. - -The syntax is as follows: - -```javascript -require.context(directory, useSubdirectories = false, regExp = /^\.\//); -``` - -Examples: - -```javascript -require.context('./test', false, /\.test\.js$/); -// a context with files from the test directory that can be required with a request endings with `.test.js`. -``` - -```javascript -require.context('../', true, /\.stories\.js$/); -// a context with all files in the parent folder and descending folders ending with `.stories.js`. -``` - -W> The arguments passed to `require.context` must be literals! - - -### context module API - -A context module exports a (require) function that takes one argument: the request. - -The exported function has 3 properties: `resolve`, `keys`, `id`. - -- `resolve` is a function and returns the module id of the parsed request. -- `keys` is a function that returns an array of all possible requests that the context module can handle. - -This can be useful if you want to require all files in a directory or matching a pattern, Example: - -```javascript -function importAll (r) { - r.keys().forEach(r); -} - -importAll(require.context('../components/', true, /\.js$/)); -``` - -```javascript -var cache = {}; - -function importAll (r) { - r.keys().forEach(key => cache[key] = r(key)); -} - -importAll(require.context('../components/', true, /\.js$/)); -// At build-time cache will be populated with all required modules. -``` - -- `id` is the module id of the context module. This may be useful for `module.hot.accept`. - - -# Public Path - -The `publicPath` configuration option can be quite useful in a variety of scenarios. It allows you to specify the base path for all the assets within your application. - - -## Use Cases - -There are a few use cases in real applications where this feature becomes especially neat. Essentially, every file emitted to your `output.path` directory will be referenced from the `output.publicPath` location. This includes child chunks (created via [code splitting](/guides/code-splitting/)) and any other assets (e.g. images, fonts, etc.) that are a part of your dependency graph. - -### Environment Based - -In development for example, we might have an `assets/` folder that lives on the same level of our index page. This is fine, but what if we wanted to host all these static assets on a CDN in production? - -To approach this problem you can easily use a good old environment variable. Let's say we have a variable `ASSET_PATH`: - -``` js -import webpack from 'webpack'; - -// Try the environment variable, otherwise use root -const ASSET_PATH = process.env.ASSET_PATH || '/'; - -export default { - output: { - publicPath: ASSET_PATH - }, - - plugins: [ - // This makes it possible for us to safely use env vars on our code - new webpack.DefinePlugin({ - 'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH) - }) - ] -}; -``` - -### On The Fly - -Another possible use case is to set the `publicPath` on the fly. webpack exposes a global variable called `__webpack_public_path__` that allows you to do that. So, in your application's entry point, you can simply do this: - -```js -__webpack_public_path__ = process.env.ASSET_PATH; -``` - -That's all you need. Since we're already using the `DefinePlugin` on our -configuration, `process.env.ASSET_PATH` will always be defined so we can safely -do that. - -W> Be aware that if you use ES6 module imports in your entry file the `__webpack_public_path__` assignment will be done after the imports. In such cases, you'll have to move the public path assignment to its own dedicated module and then import it on top of your entry.js: - -```js -// entry.js -import './public-path'; -import './app'; -``` - - -# Integrations - -Let's start by clearing up a common misconception. webpack is a module bundler like [Browserify](http://browserify.org/) or [Brunch](http://brunch.io/). It is _not a task runner_ like [Make](https://www.gnu.org/software/make/), [Grunt](https://gruntjs.com/), or [Gulp](https://gulpjs.com/). Task runners handle automation of common development tasks such as linting, building, or testing your project. Compared to bundlers, task runners have a higher level focus. You can still benefit from their higher level tooling while leaving the problem of bundling to webpack. - -Bundlers help you get your JavaScript and stylesheets ready for deployment, transforming them into a format that's suitable for the browser. For example, JavaScript can be [minified](/plugins/terser-webpack-plugin) or [split into chunks](/guides/code-splitting) and [lazy-loaded](/guides/lazy-loading) to improve performance. Bundling is one of the most important challenges in web development, and solving it well can remove a lot of pain from the process. - -The good news is that, while there is some overlap, task runners and bundlers can play well together if approached in the right way. This guide provides a high-level overview of how webpack can be integrated into some of the more popular task runners. - - -## NPM Scripts - -Often webpack users use npm [`scripts`](https://docs.npmjs.com/misc/scripts) as their task runner. This is a good starting point. Cross-platform support can become a problem, but there are several workarounds for that. Many, if not most users, get by with simple npm `scripts` and various levels of webpack configuration and tooling. - -So while webpack's core focus is bundling, there are a variety of extensions that can enable you to use it for jobs typical of a task runner. Integrating a separate tool adds complexity, so be sure to weigh the pros and cons before going forward. - - -## Grunt - -For those using Grunt, we recommend the [`grunt-webpack`](https://www.npmjs.com/package/grunt-webpack) package. With `grunt-webpack` you can run webpack or [webpack-dev-server](https://github.com/webpack/webpack-dev-server) as a task, get access to stats within [template tags](https://gruntjs.com/api/grunt.template), split development and production configurations and more. Start by installing `grunt-webpack` as well as `webpack` itself if you haven't already: - -``` bash -npm install --save-dev grunt-webpack webpack -``` - -Then register a configuration and load the task: - -__Gruntfile.js__ - -``` js -const webpackConfig = require('./webpack.config.js'); - -module.exports = function(grunt) { - grunt.initConfig({ - webpack: { - options: { - stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development' - }, - prod: webpackConfig, - dev: Object.assign({ watch: true }, webpackConfig) - } - }); - - grunt.loadNpmTasks('grunt-webpack'); -}; -``` - -For more information, please visit the [repository](https://github.com/webpack-contrib/grunt-webpack). - - -## Gulp - -Gulp is also a fairly straightforward integration with the help of the [`webpack-stream`](https://github.com/shama/webpack-stream) package (a.k.a. `gulp-webpack`). In this case, it is unnecessary to install `webpack` separately as it is a direct dependency of `webpack-stream`: - -``` bash -npm install --save-dev webpack-stream -``` - -Just `require('webpack-stream')` instead of `webpack` and optionally pass it an configuration: - -__gulpfile.js__ - -``` js -var gulp = require('gulp'); -var webpack = require('webpack-stream'); -gulp.task('default', function() { - return gulp.src('src/entry.js') - .pipe(webpack({ - // Any configuration options... - })) - .pipe(gulp.dest('dist/')); -}); -``` - -For more information, please visit the [repository](https://github.com/shama/webpack-stream). - - -## Mocha - -The [`mocha-webpack`](https://github.com/zinserjan/mocha-webpack) utility can be used for a clean integration with Mocha. The repository offers more details on the pros and cons but essentially `mocha-webpack` is a simple wrapper that provides almost the same CLI as Mocha itself and provides various webpack functionality like an improved watch mode and improved path resolution. Here is a small example of how you would install it and use it to run a test suite (found within `./test`): - -``` bash -npm install --save-dev webpack mocha mocha-webpack -mocha-webpack 'test/**/*.js' -``` - -For more information, please visit the [repository](https://github.com/zinserjan/mocha-webpack). - - -## Karma - -The [`karma-webpack`](https://github.com/webpack-contrib/karma-webpack) package allows you to use webpack to pre-process files in [Karma](http://karma-runner.github.io/1.0/index.html). It also makes use of [`webpack-dev-middleware`](https://github.com/webpack/webpack-dev-middleware) and allows passing configurations for both. A simple example may look something like this: - -``` bash -npm install --save-dev webpack karma karma-webpack -``` - -__karma.conf.js__ - -``` js -module.exports = function(config) { - config.set({ - files: [ - { pattern: 'test/*_test.js', watched: false }, - { pattern: 'test/**/*_test.js', watched: false } - ], - preprocessors: { - 'test/*_test.js': [ 'webpack' ], - 'test/**/*_test.js': [ 'webpack' ] - }, - webpack: { - // Any custom webpack configuration... - }, - webpackMiddleware: { - // Any custom webpack-dev-middleware configuration... - } - }); -}; -``` - -For more information, please visit the [repository](https://github.com/webpack-contrib/karma-webpack). diff --git a/src/content/loaders/_loaders_all.md b/src/content/loaders/_loaders_all.md deleted file mode 100644 index a16e6814c65b..000000000000 --- a/src/content/loaders/_loaders_all.md +++ /dev/null @@ -1,75 +0,0 @@ - - -# Loaders - -webpack enables use of [loaders](/concepts/loaders) to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js. - -Loaders are activated by using `loadername!` prefixes in `require()` statements, or are automatically applied via regex from your webpack configuration – see [configuration](/concepts/loaders#configuration). - - -## Files - -- [`raw-loader`](/loaders/raw-loader) Loads raw content of a file (utf-8) -- [`val-loader`](/loaders/val-loader) Executes code as module and consider exports as JS code -- [`url-loader`](/loaders/url-loader) Works like the file loader, but can return a [data URL](https://tools.ietf.org/html/rfc2397) if the file is smaller than a limit -- [`file-loader`](/loaders/file-loader) Emits the file into the output folder and returns the (relative) URL -- [`ref-loader`](https://www.npmjs.com/package/ref-loader) Create dependencies between any files manually - - -## JSON - -- [`json-loader`](/loaders/json-loader) Loads a [JSON](http://json.org/) file (included by default) -- [`json5-loader`](/loaders/json5-loader) Loads and transpiles a [JSON 5](https://json5.org/) file -- [`cson-loader`](https://github.com/awnist/cson-loader) Loads and transpiles a [CSON](https://github.com/bevry/cson#what-is-cson) file - - -## Transpiling - -- [`script-loader`](/loaders/script-loader) Executes a JavaScript file once in global context (like in script tag), requires are not parsed -- [`babel-loader`](/loaders/babel-loader) Loads ES2015+ code and transpiles to ES5 using [Babel](https://babeljs.io/) -- [`buble-loader`](https://github.com/sairion/buble-loader) Loads ES2015+ code and transpiles to ES5 using [Bublé](https://buble.surge.sh/guide/) -- [`traceur-loader`](https://github.com/jupl/traceur-loader) Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler#readme) -- [`ts-loader`](https://github.com/TypeStrong/ts-loader) or [`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader) Loads [TypeScript](https://www.typescriptlang.org/) 2.0+ like JavaScript -- [`coffee-loader`](/loaders/coffee-loader) Loads [CoffeeScript](http://coffeescript.org/) like JavaScript -- [`fengari-loader`](https://github.com/fengari-lua/fengari-loader/) Loads Lua code using [fengari](https://fengari.io/) - - -## Templating - -- [`html-loader`](/loaders/html-loader) Exports HTML as string, require references to static resources -- [`pug-loader`](https://github.com/pugjs/pug-loader) Loads Pug and Jade templates and returns a function -- [`markdown-loader`](https://github.com/peerigon/markdown-loader) Compiles Markdown to HTML -- [`react-markdown-loader`](https://github.com/javiercf/react-markdown-loader) Compiles Markdown to a React Component using the markdown-parse parser -- [`posthtml-loader`](https://github.com/posthtml/posthtml-loader) Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) -- [`handlebars-loader`](https://github.com/pcardune/handlebars-loader) Compiles Handlebars to HTML -- [`markup-inline-loader`](https://github.com/asnowwolf/markup-inline-loader) Inline SVG/MathML files to HTML. It’s useful when applying icon font or applying CSS animation to SVG. -- [`twig-loader`](https://github.com/zimmo-be/twig-loader) Compiles Twig templates and returns a function - -## Styling - -- [`style-loader`](/loaders/style-loader) Add exports of a module as style to DOM -- [`css-loader`](/loaders/css-loader) Loads CSS file with resolved imports and returns CSS code -- [`less-loader`](/loaders/less-loader) Loads and compiles a LESS file -- [`sass-loader`](/loaders/sass-loader) Loads and compiles a SASS/SCSS file -- [`postcss-loader`](/loaders/postcss-loader) Loads and transforms a CSS/SSS file using [PostCSS](http://postcss.org) -- [`stylus-loader`](https://github.com/shama/stylus-loader) Loads and compiles a Stylus file - - -## Linting && Testing - -- [`mocha-loader`](/loaders/mocha-loader) Tests with [mocha](https://mochajs.org/) (Browser/NodeJS) -- [`eslint-loader`](https://github.com/webpack-contrib/eslint-loader) PreLoader for linting code using [ESLint](https://eslint.org/) -- [`jshint-loader`](/loaders/jshint-loader) PreLoader for linting code using [JSHint](http://jshint.com/about/) -- [`jscs-loader`](https://github.com/unindented/jscs-loader) PreLoader for code style checking using [JSCS](http://jscs.info/) -- [`coverjs-loader`](/loaders/coverjs-loader) PreLoader to determine the testing coverage using [CoverJS](https://github.com/arian/CoverJS) - - -## Frameworks - -- [`vue-loader`](https://github.com/vuejs/vue-loader) Loads and compiles [Vue Components](https://vuejs.org/v2/guide/components.html) -- [`polymer-loader`](https://github.com/webpack-contrib/polymer-webpack-loader) Process HTML & CSS with preprocessor of choice and `require()` Web Components like first-class modules -- [`angular2-template-loader`](https://github.com/TheLarkInn/angular2-template-loader) Loads and compiles [Angular](https://angular.io/) Components - - - -For more third-party loaders, see the list from [awesome-webpack](https://github.com/webpack-contrib/awesome-webpack#loaders). diff --git a/src/content/migrate/_migrate_all.md b/src/content/migrate/_migrate_all.md deleted file mode 100644 index c0c02cb9ff2b..000000000000 --- a/src/content/migrate/_migrate_all.md +++ /dev/null @@ -1,786 +0,0 @@ - - -# Migrate - -This section contains information about migrating from older versions of webpack to newer ones. - -# To v4 from v3 - -This guide only shows major changes that affect end users. For more details please see [the changelog](https://github.com/webpack/webpack/releases). - - -## Node.js v4 - -If you are still using Node.js v4 or lower, you need to upgrade your Node.js installation to Node.js v6 or higher. - - -## CLI - -The CLI has moved to a separate package: webpack-cli. You need to install it before using webpack, see [basic setup](/guides/getting-started/#basic-setup). - - -## Update plugins - -Many 3rd-party plugins need to be upgraded to their latest version to be compatible. - - -## mode - -Add the new [`mode`](/concepts/mode/) option to your config. Set it to production or development in your configuration depending on config type. - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - mode: 'production', -} -``` - -Alternatively you can pass it via CLI: `--mode production`/`--mode development` - -## Deprecated/Removed plugins - -These plugins can be removed from configuration as they are default in production mode: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NoEmitOnErrorsPlugin(), -- new ModuleConcatenationPlugin(), -- new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }) -- new UglifyJsPlugin() - ], -} -``` - -These plugins are default in development mode - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NamedModulesPlugin() - ], -} -``` - -These plugins were deprecated and are now removed: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NoErrorsPlugin(), -- new NewWatchingPlugin() - ], -} -``` - - -## CommonsChunkPlugin - -The `CommonsChunkPlugin` was removed. Instead the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) options can be used. - -See documentation of the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) for more details. The default configuration may already suit your needs. - -T> When generating the HTML from the stats you can use `optimization.splitChunks.chunks: "all"` which is the optimal configuration in most cases. - -## import() and CommonJS - -When using `import()` to load non-ESM the result has changed in webpack 4. Now you need to access the `default` property to get the value of `module.exports`. - -__non-esm.js__ - -``` javascript -module.exports = { - sayHello: () => { - console.log('hello world'); - } -}; -``` - -__example.js__ - -``` javascript -function sayHello() { - import('./non-esm.js').then(module => { - module.default.sayHello(); - }); -} -``` - -## json and loaders - -When using a custom loader to transform `.json` files you now need to change the module `type`: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - rules: [ - { - test: /config\.json$/, - loader: 'special-loader', -+ type: 'javascript/auto', - options: {...} - } - ] -}; -``` - -When still using the `json-loader`, it can be removed: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - rules: [ - { -- test: /\.json$/, -- loader: 'json-loader' - } - ] -}; -``` - -## module.loaders - -`module.loaders` were deprecated since webpack 2 and are now removed in favor of [`module.rules`](/configuration/module/#rule). - - -# To v2 or v3 from v1 - -The following sections describe the major changes from webpack 1 to 2. - -T> Note that there were far fewer changes between 2 and 3, so that migration shouldn't be too bad. If you are running into issues, please see [the changelog](https://github.com/webpack/webpack/releases) for details. - - -## `resolve.root`, `resolve.fallback`, `resolve.modulesDirectories` - -These options were replaced by a single option `resolve.modules`. See [resolving](/configuration/resolve) for more usage. - -``` diff - resolve: { -- root: path.join(__dirname, "src") -+ modules: [ -+ path.join(__dirname, "src"), -+ "node_modules" -+ ] - } -``` - - -## `resolve.extensions` - -This option no longer requires passing an empty string. This behavior was moved to `resolve.enforceExtension`. See [resolving](/configuration/resolve) for more usage. - - -## `resolve.*` - -Several APIs were changed here. Not listed in detail as it's not commonly used. See [resolving](/configuration/resolve) for details. - - -## `module.loaders` is now `module.rules` - -The old loader configuration was superseded by a more powerful rules system, which allows configuration of loaders and more. -For compatibility reasons, the old `module.loaders` syntax is still valid and the old names are parsed. -The new naming conventions are easier to understand and are a good reason to upgrade the configuration to using `module.rules`. - -``` diff - module: { -- loaders: [ -+ rules: [ - { - test: /\.css$/, -- loaders: [ -- "style-loader", -- "css-loader?modules=true" -+ use: [ -+ { -+ loader: "style-loader" -+ }, -+ { -+ loader: "css-loader", -+ options: { -+ modules: true -+ } -+ } - ] - }, - { - test: /\.jsx$/, - loader: "babel-loader", // Do not use "use" here - options: { - // ... - } - } - ] - } -``` - - -## Chaining loaders - -Like in webpack 1, loaders can be chained to pass results from loader to loader. Using the [rule.use](/configuration/module#rule-use) - configuration option, `use` can be set to an array of loaders. -In webpack 1, loaders were commonly chained with `!`. This style is only supported using the legacy option `module.loaders`. - -``` diff - module: { -- loaders: [{ -+ rules: [{ - test: /\.less$/, -- loader: "style-loader!css-loader!less-loader" -+ use: [ -+ "style-loader", -+ "css-loader", -+ "less-loader" -+ ] - }] - } -``` - - -## Automatic `-loader` module name extension removed - -It is not possible anymore to omit the `-loader` extension when referencing loaders: - -``` diff - module: { - rules: [ - { - use: [ -- "style", -+ "style-loader", -- "css", -+ "css-loader", -- "less", -+ "less-loader", - ] - } - ] - } -``` - -You can still opt-in to the old behavior with the `resolveLoader.moduleExtensions` configuration option, but this is not recommended. - -``` diff -+ resolveLoader: { -+ moduleExtensions: ["-loader"] -+ } -``` - -See [#2986](https://github.com/webpack/webpack/issues/2986) for the reason behind this change. - - -## `json-loader` is not required anymore - -When no loader has been configured for a JSON file, webpack will automatically try to load the JSON -file with the [`json-loader`](https://github.com/webpack-contrib/json-loader). - -``` diff - module: { - rules: [ -- { -- test: /\.json/, -- loader: "json-loader" -- } - ] - } -``` - -[We decided to do this](https://github.com/webpack/webpack/issues/3363) in order to iron out environment differences - between webpack, node.js and browserify. - - -## Loaders in configuration resolve relative to context - -In __webpack 1__, configured loaders resolve relative to the matched file. However, in __webpack 2__, configured loaders resolve relative to the `context` option. - -This solves some problems with duplicate modules caused by loaders when using `npm link` or referencing modules outside of the `context`. - -You may remove some hacks to work around this: - -``` diff - module: { - rules: [ - { - // ... -- loader: require.resolve("my-loader") -+ loader: "my-loader" - } - ] - }, - resolveLoader: { -- root: path.resolve(__dirname, "node_modules") - } -``` - - -## `module.preLoaders` and `module.postLoaders` were removed: - -``` diff - module: { -- preLoaders: [ -+ rules: [ - { - test: /\.js$/, -+ enforce: "pre", - loader: "eslint-loader" - } - ] - } -``` - - -## `UglifyJsPlugin` sourceMap - -The `sourceMap` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. This means that if you are using source maps for minimized code or want correct line numbers for uglifyjs warnings, you need to set `sourceMap: true` for `UglifyJsPlugin`. - -``` diff - devtool: "source-map", - plugins: [ - new UglifyJsPlugin({ -+ sourceMap: true - }) - ] -``` - - -## `UglifyJsPlugin` warnings - -The `compress.warnings` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. -This means that if you want to see uglifyjs warnings, you need to set `compress.warnings` to `true`. - -``` diff - devtool: "source-map", - plugins: [ - new UglifyJsPlugin({ -+ compress: { -+ warnings: true -+ } - }) - ] -``` - - -## `UglifyJsPlugin` minimize loaders - -`UglifyJsPlugin` no longer switches loaders into minimize mode. The `minimize: true` setting needs to be passed via loader options in the long-term. See loader documentation for relevant options. - -The minimize mode for loaders will be removed in webpack 3 or later. - -To keep compatibility with old loaders, loaders can be switched to minimize mode via plugin: - -``` diff - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ minimize: true -+ }) - ] -``` - - -## `DedupePlugin` has been removed - -`webpack.optimize.DedupePlugin` isn't needed anymore. Remove it from your configuration. - - -## `BannerPlugin` - breaking change - -`BannerPlugin` no longer accepts two parameters, but a single options object. - -``` diff - plugins: [ -- new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true}); -+ new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true}); - ] -``` - - -## `OccurrenceOrderPlugin` is now on by default - -The `OccurrenceOrderPlugin` is now enabled by default and has been renamed (`OccurenceOrderPlugin` in webpack 1). -Thus make sure to remove the plugin from your configuration: - -``` diff - plugins: [ - // webpack 1 -- new webpack.optimize.OccurenceOrderPlugin() - // webpack 2 -- new webpack.optimize.OccurrenceOrderPlugin() - ] -``` - - -## `ExtractTextWebpackPlugin` - breaking change - -[ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) requires version 2 to work with webpack 2. - -`npm install --save-dev extract-text-webpack-plugin` - -The configuration changes for this plugin are mainly syntactical. - -### `ExtractTextPlugin.extract` - -```diff -module: { - rules: [ - { - test: /.css$/, -- loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" }) -+ use: ExtractTextPlugin.extract({ -+ fallback: "style-loader", -+ use: "css-loader", -+ publicPath: "/dist" -+ }) - } - ] -} -``` - - -### `new ExtractTextPlugin({options})` - -```diff -plugins: [ -- new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false }) -+ new ExtractTextPlugin({ -+ filename: "bundle.css", -+ disable: false, -+ allChunks: true -+ }) -] -``` - - -## Full dynamic requires now fail by default - -A dependency with only an expression (i. e. `require(expr)`) will now create an empty context instead of the context of the complete directory. - -Code like this should be refactored as it won't work with ES2015 modules. If this is not possible you can use the `ContextReplacementPlugin` to hint the compiler towards the correct resolving. - -?> Link to an article about dynamic dependencies. - -### Using custom arguments in CLI and configuration - -If you abused the CLI to pass custom arguments to the configuration like so: - -`webpack --custom-stuff` - -```js -// webpack.config.js -var customStuff = process.argv.indexOf('--custom-stuff') >= 0; -/* ... */ -module.exports = config; -``` - -You may notice that this is no longer allowed. The CLI is more strict now. - -Instead there is an interface for passing arguments to the configuration. This should be used instead. Future tools may rely on this. - -`webpack --env.customStuff` - -```js -module.exports = function(env) { - var customStuff = env.customStuff; - /* ... */ - return config; -}; -``` - -See [CLI](/api/cli). - - -## `require.ensure` and AMD `require` are asynchronous - -These functions are now always asynchronous instead of calling their callback synchronously if the chunk is already loaded. - -__`require.ensure` now depends upon native `Promise`s. If using `require.ensure` in an environment that lacks them then you will need a polyfill.__ - - -## Loader configuration is through `options` - -You can _no longer_ configure a loader with a custom property in the `webpack.config.js`. It must be done through the `options`. The following configuration with the `ts` property is no longer valid with webpack 2: - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader' - }] - }, - // does not work with webpack 2 - ts: { transpileOnly: false } -}; -``` - - -### What are `options`? - -Good question. Well, strictly speaking it's 2 possible things; both ways to configure a webpack loader. Classically `options` was called `query` and was a string which could be appended to the name of the loader. Much like a query string but actually with [greater powers](https://github.com/webpack/loader-utils#parsequery): - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader?' + JSON.stringify({ transpileOnly: false }) - }] - } -}; -``` - -But it can also be a separately specified object that's supplied alongside a loader: - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader', - options: { transpileOnly: false } - }] - } -}; -``` - - -## `LoaderOptionsPlugin` context - -Some loaders need context information and read them from the configuration. This needs to be passed via loader options in the long-term. See loader documentation for relevant options. - -To keep compatibility with old loaders, this information can be passed via plugin: - -``` diff - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ options: { -+ context: __dirname -+ } -+ }) - ] -``` - - -## `debug` - -The `debug` option switched loaders to debug mode in webpack 1. This needs to be passed via loader options in long-term. See loader documentation for relevant options. - -The debug mode for loaders will be removed in webpack 3 or later. - -To keep compatibility with old loaders, loaders can be switched to debug mode via a plugin: - -``` diff -- debug: true, - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ debug: true -+ }) - ] -``` - - -## Code Splitting with ES2015 - -In webpack 1, you could use [`require.ensure()`](/api/module-methods#require-ensure) as a method to lazily-load chunks for your application: - -```javascript -require.ensure([], function(require) { - var foo = require('./module'); -}); -``` - -The ES2015 Loader spec defines [`import()`](/api/module-methods#import-) as method to load ES2015 Modules dynamically on runtime. webpack treats `import()` as a split-point and puts the requested module in a separate chunk. `import()` takes the module name as argument and returns a Promise. - -```js -function onClick() { - import('./module').then(module => { - return module.default; - }).catch(err => { - console.log('Chunk loading failed'); - }); -} -``` - -Good news: Failure to load a chunk can now be handled because they are `Promise` based. - - -## Dynamic expressions - -It's possible to pass a partial expression to `import()`. This is handled similar to expressions in CommonJS (webpack creates a [context](/plugins/context-replacement-plugin/) with all possible files). - -`import()` creates a separate chunk for each possible module. - -```js -function route(path, query) { - return import(`./routes/${path}/route`) - .then(route => new route.Route(query)); -} -// This creates a separate chunk for each possible route -``` - - -## Mixing ES2015 with AMD and CommonJS - -As for AMD and CommonJS you can freely mix all three module types (even within the same file). webpack behaves similar to babel and node-eps in this case: - -```javascript -// CommonJS consuming ES2015 Module -var book = require('./book'); - -book.currentPage; -book.readPage(); -book.default === 'This is a book'; -``` - -```javascript -// ES2015 Module consuming CommonJS -import fs from 'fs'; // module.exports map to default -import { readFileSync } from 'fs'; // named exports are read from returned object+ - -typeof fs.readFileSync === 'function'; -typeof readFileSync === 'function'; -``` - -It is important to note that you will want to tell Babel to not parse these module symbols so webpack can use them. You can do this by setting the following in your `.babelrc` or `babel-loader` options. - -__.babelrc__ - -```json -{ - "presets": [ - ["es2015", { "modules": false }] - ] -} -``` - - -## Hints - -No need to change something, but opportunities - -### Template strings - -webpack now supports template strings in expressions. This means you can start using them in webpack constructs: - -``` diff -- require("./templates/" + name); -+ require(`./templates/${name}`); -``` - - -### Configuration Promise - -webpack now supports returning a `Promise` from the configuration file. This allows async processing in your configuration file. - -__webpack.config.js__ - -```js -module.exports = function() { - return fetchLangs().then(lang => ({ - entry: '...', - // ... - plugins: [ - new DefinePlugin({ LANGUAGE: lang }) - ] - })); -}; -``` - - -### Advanced loader matching - -webpack now supports more things to match on for loaders. - -```js -module.exports = { - //... - module: { - rules: [ - { - resource: /filename/, // matches "/path/filename.js" - resourceQuery: /^\?querystring$/, // matches "?querystring" - issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js" - } - ] - } -}; -``` - - -### More CLI options - -There are some new CLI options for you to use: - -`--define process.env.NODE_ENV="production"` See [`DefinePlugin`](/plugins/define-plugin/). - -`--display-depth` displays the distance to the entry point for each module. - -`--display-used-exports` display info about which exports are used in a module. - -`--display-max-modules` sets the number for modules displayed in the output (defaults to 15). - -`-p` also defines `process.env.NODE_ENV` to `"production"` now. - - -## Loader changes - -Changes only relevant for loader authors. - - -### Cacheable - -Loaders are now cacheable by default. Loaders must opt-out if they are not cacheable. - -``` diff - // Cacheable loader - module.exports = function(source) { -- this.cacheable(); - return source; - } -``` - -``` diff - // Not cacheable loader - module.exports = function(source) { -+ this.cacheable(false); - return source; - } -``` - - -### Complex options - -__webpack 1__ only supports `JSON.stringify`-able options for loaders. - -__webpack 2__ now supports any JS object as loader options. - -Before webpack [2.2.1](https://github.com/webpack/webpack/releases/tag/v2.2.1) (i.e. from 2.0.0 through 2.2.0), using complex options required using `ident` for the `options` object to allow its reference from other loaders. __This was removed in 2.2.1__ and thus current migrations do not require any use of the `ident` key. - -```diff -{ - test: /\.ext/ - use: { - loader: '...', - options: { -- ident: 'id', - fn: () => require('./foo.js') - } - } -} -``` diff --git a/src/content/plugins/_plugins_all.md b/src/content/plugins/_plugins_all.md deleted file mode 100644 index 65d63475ab80..000000000000 --- a/src/content/plugins/_plugins_all.md +++ /dev/null @@ -1,11 +0,0 @@ - - -# MinChunkSizePlugin - -Keep chunk size above the specified limit by merging chunks that are smaller than the `minChunkSize`. - -``` js -new webpack.optimize.MinChunkSizePlugin({ - minChunkSize: 10000 // Minimum number of characters -}); -``` From 49901a1d48fe8814144672168a06b604693944a6 Mon Sep 17 00:00:00 2001 From: Axel D <SetTrend@users.noreply.github.com> Date: Fri, 14 Dec 2018 16:52:20 +0100 Subject: [PATCH 03/13] CSS rules added for printing, script added to create chapter-wide documentation files from single files. --- concatenate-docs.js | 78 + package.json | 7 +- src/components/Footer/Footer.scss | 4 + src/components/Page/Page.jsx | 2 +- src/components/Page/Page.scss | 7 + src/components/PageLinks/PageLinks.scss | 4 + src/content/_all.md | 262 + src/content/api/_api_all.md | 3189 ++++++++++ src/content/concepts/_concepts_all.md | 1086 ++++ .../configuration/_configuration_all.md | 5315 +++++++++++++++++ src/content/contribute/_contribute_all.md | 979 +++ src/content/guides/_guides_all.md | 4880 +++++++++++++++ src/content/loaders/_loaders_all.md | 75 + src/content/migrate/_migrate_all.md | 786 +++ src/content/plugins/_plugins_all.md | 11 + 15 files changed, 16681 insertions(+), 4 deletions(-) create mode 100644 concatenate-docs.js create mode 100644 src/content/_all.md create mode 100644 src/content/api/_api_all.md create mode 100644 src/content/concepts/_concepts_all.md create mode 100644 src/content/configuration/_configuration_all.md create mode 100644 src/content/contribute/_contribute_all.md create mode 100644 src/content/guides/_guides_all.md create mode 100644 src/content/loaders/_loaders_all.md create mode 100644 src/content/migrate/_migrate_all.md create mode 100644 src/content/plugins/_plugins_all.md diff --git a/concatenate-docs.js b/concatenate-docs.js new file mode 100644 index 000000000000..5d2a7c48ec0f --- /dev/null +++ b/concatenate-docs.js @@ -0,0 +1,78 @@ +// start message +console.info("\x1b[0m\x1b[36mConcatenating help files of each directory to create chapter-wide help files to be used for printing help ...\x1b[0m"); + +// ------ various includes ------ +const fs = require("fs"); +const path = require("path"); +const os = require("os"); +const front = require("front-matter"); + +// root path +const rootPath = path.join("src", "content"); + +/* getDirectoryRecursive() recursively walks through + all sub directories of the provided root path, + concatenates the MarkDown files' content in + each directory, sorted by their FrontMatter sort + attribute, and creates a compound MarkDown file + named by using the directory name, prefixed by an + underscore and suffixed by "_all.md" from the + concatenated content in the corresponding directory. +*/ +(function getDirectoryRecursive(basePath) +{ + // log current working directory + console.log("\x1b[0m\x1b[32m " + basePath + "\x1b[0m"); + + // create destination file name of compound file + const targetFilePath = path.join(basePath, `${basePath.substr(rootPath.length).replace(/[/\\]/, "_")}_all.md`); + + if (fs.existsSync(targetFilePath)) fs.unlinkSync(targetFilePath); // delete target file if it already exists + + fs.readdir(basePath, function (err, fileNames) // list current working directory + { + if (err) throw err; + + let fileContents = []; + + for (let file of fileNames) // for each directory entry ... + { + const fullPath = path.join(basePath, file); + + if (fs.statSync(fullPath).isDirectory()) getDirectoryRecursive(fullPath); // if the directory entry is a directory, recurse into that directory + else if (fullPath.endsWith(".md")) // if the directory entry is a MarkDown file, add it to the list of files to be processed + { + let fc = fileContents[fileContents.length] = front(fs.readFileSync(fullPath).toString()); + + if (!fc.attributes.sort) --fileContents.length; // only include files providing a FrontMatter "sort" attribute + } + } + + // sort MarkDown files by FrontMatter "sort" attribute (QuickSort) + for (let i = 0;i < fileContents.length - 1;++i) + for (let j = i + 1;j < fileContents.length;++j) + { + const left = fileContents[i].attributes, right = fileContents[j].attributes; + + if (left.sort > right.sort + || left.sort == right.sort && left.title > right.title) + [fileContents[i], fileContents[j]] = [fileContents[j], fileContents[i]]; + } + + // write compound target file + const targetFile = fs.createWriteStream(targetFilePath); + + targetFile.on("error", (error) => { throw error; }); + + for (let file of fileContents) + { + targetFile.write(os.EOL + os.EOL + "# " + file.attributes.title + os.EOL); // use FrontMatter "title" attribute as main heading of target file + targetFile.write(file.body); + } + + targetFile.end(); + }); +})(rootPath); + +// end message +process.on("exit", () => { console.info("\x1b[0m\x1b[36mSuccessfully created \"_all.md\" help files in each directory within \"" + rootPath + "\".\x1b[0m"); }); \ No newline at end of file diff --git a/package.json b/package.json index 96f6834bb6f5..931acebc9f52 100644 --- a/package.json +++ b/package.json @@ -26,18 +26,19 @@ "scripts": { "start": "run-s -n init:generated fetch start-only", "start-only": "node ./antwar.bootstrap.js develop", - "build": "npm run init:generated && npm run fetch && rm -rf build/ && node ./antwar.bootstrap.js build && npm run sitemap && echo webpack.js.org > build/CNAME", + "build": "npm run init:generated && npm run fetch && rm -rf build/ && node ./antwar.bootstrap.js build && npm run sitemap && npm run chapterize && echo webpack.js.org > build/CNAME", "build-test": "npm run build && http-server build/", "deploy": "gh-pages -d build", "fetch": "sh src/scripts/fetch.sh", "init:generated": "mkdirp ./generated/loaders && mkdirp ./generated/plugins ", "lint": "run-s lint:*", "lint:js": "eslint . --ext .js,.jsx,.md", - "lint:markdown": "markdownlint --rules markdownlint-rule-emphasis-style --config ./.markdownlint.json *.md ./src/content/*.md ./src/content/**/*.md", + "lint:markdown": "markdownlint --rules markdownlint-rule-emphasis-style --config ./.markdownlint.json --ignore ./src/content/**/*_all.md *.md ./src/content/**/*.md", "lint:social": "alex . -q", "lint:prose": "cp .proselintrc ~/ && proselint src/content", "test": "npm run lint", - "sitemap": "cd build && sitemap-static --prefix=https://webpack.js.org/ > sitemap.xml" + "sitemap": "cd build && sitemap-static --prefix=https://webpack.js.org/ > sitemap.xml", + "chapterize": "node ./concatenate-docs.js" }, "husky": { "hooks": { diff --git a/src/components/Footer/Footer.scss b/src/components/Footer/Footer.scss index 106d52ec0de3..4388e8be401c 100644 --- a/src/components/Footer/Footer.scss +++ b/src/components/Footer/Footer.scss @@ -4,6 +4,10 @@ .footer { width: 100%; flex: 0 0 auto; + + @media print { + display: none !important; + } } .footer__inner { diff --git a/src/components/Page/Page.jsx b/src/components/Page/Page.jsx index a21ce4d20156..e2b93794f766 100644 --- a/src/components/Page/Page.jsx +++ b/src/components/Page/Page.jsx @@ -81,7 +81,7 @@ const Page = ({ page, section }) => { )} { contributors.length > 0 && ( - <div> + <div className="contributors__section"> <hr /> <h3>Contributors</h3> <Contributors contributors={ contributors } /> diff --git a/src/components/Page/Page.scss b/src/components/Page/Page.scss index 85c664e2fdfe..91b1b94bcafe 100644 --- a/src/components/Page/Page.scss +++ b/src/components/Page/Page.scss @@ -29,3 +29,10 @@ padding: 1.5em; } } + +.contributors__section, .interactive +{ + @media print { + display: none !important; + } +} \ No newline at end of file diff --git a/src/components/PageLinks/PageLinks.scss b/src/components/PageLinks/PageLinks.scss index 7f45b7ff1526..60624bdd51fc 100644 --- a/src/components/PageLinks/PageLinks.scss +++ b/src/components/PageLinks/PageLinks.scss @@ -2,6 +2,10 @@ @import 'functions'; .page-links { + @media print { + display: none !important; + } + position: absolute; display: none; top: 1.5em; diff --git a/src/content/_all.md b/src/content/_all.md new file mode 100644 index 000000000000..fb91d2979380 --- /dev/null +++ b/src/content/_all.md @@ -0,0 +1,262 @@ + + +# Comparison + +webpack is not the only module bundler out there. If you are choosing between using webpack or any of the bundlers below, here is a feature-by-feature comparison on how webpack fares against the current competition. + +| Feature | webpack/webpack | jrburke/requirejs | substack/node-browserify | jspm/jspm-cli | rollup/rollup | brunch/brunch | +|---------|-----------------|-------------------|--------------------------|---------------|---------------|---------------| +| Additional chunks are loaded on demand | __yes__ | __yes__ | no | [System.import](https://github.com/systemjs/systemjs/blob/master/docs/system-api.md#systemimportmodulename--normalizedparentname---promisemodule) | no | no | +| AMD `define` | __yes__ | __yes__ | [deamdify](https://github.com/jaredhanson/deamdify) | yes | [rollup-plugin-amd](https://github.com/piuccio/rollup-plugin-amd) | yes | +| AMD `require` | __yes__ | __yes__ | no | yes | no | yes | +| AMD `require` loads on demand | __yes__ | with manual configuration | no | yes | no | no | +| CommonJS `exports` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | +| CommonJS `require` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | +| CommonJS `require.resolve` | __yes__ | no | no | no | no | | +| Concat in require `require("./fi" + "le")` | __yes__ | no♦ | no | no | no | | +| Debugging support | __SourceUrl, SourceMaps__ | not required | SourceMaps | __SourceUrl, SourceMaps__ | __SourceUrl, SourceMaps__ | SourceMaps | +| Dependencies | 19MB / 127 packages | 11MB / 118 packages | __1.2MB / 1 package__ | 26MB / 131 packages | ?MB / 3 packages | | +| ES2015 `import`/`export` | __yes__ (webpack 2) | no | no | __yes__ | __yes__ | yes, via [es6 module transpiler](https://github.com/gcollazo/es6-module-transpiler-brunch) +| Expressions in require (guided) `require("./templates/" + template)` | __yes (all files matching included)__ | no♦ | no | no | no | no | +| Expressions in require (free) `require(moduleName)` | with manual configuration | no♦ | no | no | no | | +| Generate a single bundle | __yes__ | yes♦ | yes | yes | yes | yes | +| Indirect require `var r = require; r("./file")` | __yes__ | no♦ | no | no | no | | +| Load each file separate | no | yes | no | yes | no | no | +| Mangle path names | __yes__ | no | partial | yes | not required (path names are not included in the bundle) | no | +| Minimizing | terser | uglify, closure compiler | [uglifyify](https://github.com/hughsk/uglifyify) | yes | [uglify-plugin](https://github.com/TrySound/rollup-plugin-uglify) | [UglifyJS-brunch](https://github.com/brunch/uglify-js-brunch) +| Multi pages build with common bundle | with manual configuration | __yes__ | with manual configuration | with bundle arithmetic | no | no| +| Multiple bundles | __yes__ | with manual configuration | with manual configuration | yes | no | yes | +| Node.js built-in libs `require("path")` | __yes__ | no | __yes__ | __yes__ | [node-resolve-plugin](https://github.com/rollup/rollup-plugin-node-resolve) | | +| Other Node.js stuff | process, __dir/filename, global | - | process, __dir/filename, global | process, __dir/filename, global for cjs | global ([commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs)) | | +| Plugins | __yes__ | yes | __yes__ | yes | yes | yes | +| Preprocessing | __loaders, [transforms](https://github.com/webpack-contrib/transform-loader)__ | loaders | transforms | plugin translate | plugin transforms | compilers, optimizers | +| Replacement for browser | `web_modules`, `.web.js`, package.json field, alias config option | alias option | package.json field, alias option | package.json, alias option | no | | +| Requirable files | file system | __web__ | file system | through plugins | file system or through plugins | file system | +| Runtime overhead | __243B + 20B per module + 4B per dependency__ | 14.7kB + 0B per module + (3B + X) per dependency | 415B + 25B per module + (6B + 2X) per dependency | 5.5kB for self-executing bundles, 38kB for full loader and polyfill, 0 plain modules, 293B CJS, 139B ES2015 System.register before gzip | __none for ES2015 modules__ (other formats may have) | | +| Watch mode | yes | not required | [watchify](https://github.com/browserify/watchify) | not needed in dev | [rollup-watch](https://github.com/rollup/rollup-watch) | yes | + +♦ in production mode (opposite in development mode) + +X is the length of the path string + + +## Bundling vs. Loading + +It's important to note some key differences between _loading_ and _bundling_ modules. A tool like [SystemJS](https://github.com/systemjs/systemjs), which can be found under the hood of [JSPM](https://github.com/jspm/jspm-cli), is used to load and transpile modules at runtime in the browser. This differs significantly from webpack, where modules are transpiled (through "loaders") and bundled before hitting the browser. + +Each method has its advantages and disadvantages. Loading and transpiling modules at runtime can add a lot of overhead for larger sites and applications comprised of many modules. For this reason, SystemJS makes more sense for smaller projects where fewer modules are required. However, this may change a bit as [HTTP/2](https://http2.github.io/) will improve the speed at which files can be transferred from server to client. Note that HTTP/2 doesn't change anything about _transpiling_ modules, which will always take longer when done client-side. + + +# Branding Guidelines + +Here you can find __webpack__ project brand guidelines, assets, and license. See our official [media repository](https://github.com/webpack/media) for more information and to find the [license](https://github.com/webpack/media/blob/master/LICENSE) that governs this work. Click any of the images to download them. + + +## The Name + +webpack should __always__ be written in lower-case letters, even at the beginning of a sentence. + + +## Logo + +The webpack logo should be placed on a white background with enough space around it like this: + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-white-bg.png" alt="webpack logo default with proper spacing on light background" /> + +[svg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.jpg) + +Just double the size of the inner dark blue cube to get an idea how much space the logo should have. + +For dark backgrounds, you can use the negative version of the logo: + +<div style="display: block; background: #111;"> + <img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-dark-bg.png" alt="webpack logo default with proper spacing on light background" /> +</div> + +[svg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.jpg) + +T> Please use the __icon + text__ whenever possible. + + +## Icon only + +__The icon is designed to be used in layout-constrained areas. As previously stated, please prefer icon + text.__ + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon.png" width="250" alt="icon example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon.jpg) + +Square-sized icon for bigger areas (like avatars or profile pictures): + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-big.png" width="250" alt="icon square big example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon-square-big.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-big.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-big.jpg) + +Square-sized icon for smaller areas (like favicons): + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-small.png" width="50" alt="icon square small example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon-square-small.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-small.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-small.jpg) + +T> For those of you following our guidelines and have gotten this far, we've made a special smaller size image used especially for custom emoji (like in a slack or gitter channel ;)) + +<img src="/assets/icon-square-small-slack.png" width="50" alt="icon square small example"> + + +## Font + +We use the beautiful [Geomanist Medium](http://atipofoundry.com/fonts/geomanist) font from the extremely talented folks at the [Atipo Foundry](http://atipofoundry.com/) who provide the entire font family at a 'pay what you want' model. + + +## Color Palette + +The following colors are used throughout the site in various combinations and on our fancy clothing line launched with the help of [Open Collective](https://opencollective.com/) and [Threadless](https://medium.com/u/840563ee2a56) over at the [official webpack store](https://webpack.threadless.com/collections/the-final-release-collection/)! + +| Color Name | HEX Code | RGB Code | Sample +|---------------|---------------|-----------------------|------------------------------- +| Malibu: | HEX `#8dd6f9` | `rgb: 141, 214, 249` | <div style="background-color: #8dd6f9;"> </div> +| Denim: | HEX `#1d78c1` | `rgb: 29, 120, 193` | <div style="background-color: #1d78c1;"> </div> +| Fiord: | HEX `#465E69` | `rgb: 70, 94, 105` | <div style="background-color: #465E69;"> </div> +| Outer Space: | HEX `#2B3A42` | `rgb: 43, 58, 66` | <div style="background-color: #2B3A42;"> </div> +| White: | HEX `#ffffff` | `rgb: 255, 255, 255` | <div style="background-color: #ffffff;"> </div> +| Concrete: | HEX `#f2f2f2` | `rgb: 242, 242, 242` | <div style="background-color: #f2f2f2;"> </div> +| Alto: | HEX `#dedede` | `rgb: 222, 222, 222` | <div style="background-color: #dedede;"> </div> +| Dusty Gray: | HEX `#999999` | `rgb: 153, 153, 153` | <div style="background-color: #999999;"> </div> +| Dove Gray: | HEX `#666666` | `rgb: 102, 102, 102` | <div style="background-color: #666666;"> </div> +| Emperor: | HEX `#535353` | `rgb: 83, 83, 83` | <div style="background-color: #535353;"> </div> +| Mine Shaft: | HEX `#333333` | `rgb: 51, 51, 51` | <div style="background-color: #333333;"> </div> + +In addition, you can grab the following file types directly from these links: + +[psd](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.psd) | [png](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.png) + | [ai](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.ai) | [svg](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.svg) + + +## License + +The logo and the brand name are __not MIT licensed__. Please check [our LICENSE](https://github.com/webpack/media/blob/master/LICENSE) for usage guidelines. + + +# Glossary + +This index lists common terms used throughout the webpack ecosystem. + + +## A + +- [__Asset__](/guides/asset-management/): This a general term for the images, fonts, media, and any other kind of files that are typically used in websites and other applications. These typically end up as individual files within the [output](/glossary#o) but can also be inlined via things like the [style-loader](/loaders/style-loader) or [url-loader](/loaders/url-loader). + + +## B + +- [__Bundle__](/guides/getting-started/#creating-a-bundle): Produced from a number of distinct modules, bundles contain the final versions of source files that have already undergone the loading and compilation process. +- [__Bundle Splitting__](/guides/code-splitting): This process offers one way of optimizing a build, allowing webpack to generate multiple bundles for a single application. As a result, each bundle can be isolated from changes effecting others, reducing the amount of code that needs to be republished and therefore re-downloaded by the client and taking advantage of browser caching. + + +## C + +- __Chunk__: This webpack-specific term is used internally to manage the bundling process. Bundles are composed out of chunks, of which there are several types (e.g. entry and child). Typically, _chunks_ directly correspond with the output _bundles_ however, there are some configurations that don't yield a one-to-one relationship. +- [__Code Splitting__](/guides/code-splitting/): Refers to dividing your code into various bundles/chunks which you can then load on demand instead of loading a single bundle containing everything. +- [__Configuration__](/concepts/configuration/): webpack config file is a plain old JavaScript file that exports an object. This object is then processed by webpack based upon its defined properties. + + +## D + +- [__Dependency Graph__](/concepts/dependency-graph): Any time one file depends on another, webpack treats this as a _dependency_. Starting from an entry point(s), webpack recursively builds a dependency graph that includes every module/asset your application needs. + + +## E + +- [__Entry Point__](/concepts/entry-points): The entry point tells webpack where to start and follows the graph of dependencies to know what to bundle. You can think of your application's entry point(s) as the __contextual root(s)__ of what you want bundled. + + +## F + +## G + +## H + +- [__Hot Module Replacement (HMR)__](/concepts/hot-module-replacement): A process that exchanges, adds, or removes `modules` while an application is running without a full page reload. + + +## I + +## J + +## K + +## L + +- [__Loaders__](/concepts/loaders): Transformations that are applied on the source code of a module. They allow you to pre-process files as you `require()` or "load" them. Similar to a 'task-runner'. + + +## M + +- [__Module__](/concepts/modules): Discrete chunks of functionality that provide a smaller surface area than a full program. Well-written modules provide solid abstractions and encapsulation boundaries which make up a coherent design and clear purpose. +- [__Module Resolution__](/concepts/module-resolution/): A module can be required as a dependency from another module and a resolver is a library which helps in locating a module by its absolute path.. Modules are searched for inside all directories specified in `resolve.modules`. + + +## N + +## O + +- [__Output__](/concepts/output): Option(s) specifying where to output the compiled files to disk. + > _Note, that while there can be multiple entry points, only one output configuration is specified._ + + +## P + +- [__Plugin__](/concepts/plugins): A JavaScript object that has an `apply` property. This `apply` property is called by the webpack compiler, giving access to the entire compilation lifecycle. These packages will typically extend compilation functionality in one way or another. + + +## Q + +## R + +- [__Request__](/guides/dependency-management/): Refers to the expression in the require/import statement, e.g. _require("./template/" + name + ".ejs")_, the request is _"./template/" + name + ".ejs"_. + +## S + +## T + +- [__Target__](/configuration/target/): User configured deployment target(s) [listed here](/configuration/target/) to compile for a specific environment like the browser, NodeJS, or Electron. +- [__Tree Shaking__](/guides/tree-shaking/): Unused/Excess code elimination, or more precisely, live code importing. Compilers like webpack will accomplish this by analyzing the various kinds `import` statements and usage of the imported code to determine what parts of dependencies are actually being utilized, dropping parts of the "tree" that are not. + + +## U + +## V + +- [__Vendor Entry Point__](/concepts/entry-points/#separate-app-and-vendor-entries): Create dependency graphs starting at both `app.js` and `vendors.js`. These graphs are completely separate and independent of each other to allow leverage of `CommonsChunkPlugin` and extract any vendor references from your app bundle into your vendor bundle. Helps achieve a common pattern in webpack known as [long-term vendor-caching](/guides/caching/). + + +## W + +- [__webpack__](/): A highly configurable [module](/concepts/modules) bundler for modern JavaScript applications + + +## X + +## Y + +## Z + + +# License + +## webpack + +webpack is [MIT licensed](https://github.com/webpack/webpack/blob/master/LICENSE). + +## webpack logo and icon + +The webpack logo and icon are under a different license which can be +found [here](https://github.com/webpack/media). + +## webpack documentation + +The content on [https://webpack.js.org/](https://webpack.js.org/) is available under [Creative Commons BY 4.0](https://creativecommons.org/licenses/by/4.0/) license meaning attribution is required should you use the content elsewhere. + +## webpack code samples + +The code samples use [CC0 1.0 Universal (CC0 1.0) (Public Domain)](https://creativecommons.org/publicdomain/zero/1.0/) and you are free to use them as you like. diff --git a/src/content/api/_api_all.md b/src/content/api/_api_all.md new file mode 100644 index 000000000000..d54e6da2b86f --- /dev/null +++ b/src/content/api/_api_all.md @@ -0,0 +1,3189 @@ + + +# Compiler Hooks + +The `Compiler` module is the main engine that creates a compilation instance +with all the options passed through the [CLI](/api/cli) or [Node API](/api/node). It extends the +`Tapable` class in order to register and call plugins. Most user facing plugins +are first registered on the `Compiler`. + +T> This module is exposed as `webpack.Compiler` and can be used directly. See +[this example](https://github.com/pksjce/webpack-internal-examples/tree/master/compiler-example) +for more information. + +When developing a plugin for webpack, you might want to know where each hook is called. To learn this, search for `hooks.<hook name>.call` across the webpack source + + +## Watching + +The `Compiler` supports [watching](/api/node/#watching) which monitors the file +system and recompiles as files change. When in watch mode, the compiler will +emit the additional events such as `watchRun`, `watchClose`, and `invalid`. +This is typically used in [development](/guides/development), usually under +the hood of tools like `webpack-dev-server`, so that the developer doesn't +need to re-compile manually every time. Watch mode can also be entered via the +[CLI](/api/cli/#watch-options). + + +## Hooks + +The following lifecycle hooks are exposed by the `compiler` and can be accessed +as such: + +``` js +compiler.hooks.someHook.tap(/* ... */); +``` + +Depending on the hook type, `tapAsync` and `tapPromise` may also be available. + +For the description of hook types, see [the Tapable docs](https://github.com/webpack/tapable#hook-types). + + +### `entryOption` + +`SyncBailHook` + +Executes a plugin after [the `entry` configuration](https://webpack.js.org/configuration/entry-context/#entry) from webpack options has been processed. + + +### `afterPlugins` + +`SyncHook` + +Runs a plugin after setting up initial set of plugins. + +Parameters: `compiler` + + +### `afterResolvers` + +`SyncHook` + +Executes a plugin after resolver setup is complete. + +Parameters: `compiler` + + +### `environment` + +`SyncHook` + +Runs a plugin before the environment is prepared. + + +### `afterEnvironment` + +`SyncHook` + +Executes a plugin a environment setup is complete. + + +### `beforeRun` + +`AsyncSeriesHook` + +Adds a hook right before `compiler.run()` is executed. + +Parameters: `compiler` + + +### `run` + +`AsyncSeriesHook` + +Hook into the compiler before it begins reading records. + +Parameters: `compiler` + + +### `watchRun` + +`AsyncSeriesHook` + +Executes a plugin during watch mode after a new compilation is triggered +but before the compilation is actually started. + +Parameters: `compiler` + + +### `normalModuleFactory` + +`SyncHook` + +Runs a plugin after a `NormalModuleFactory` is created. + +Parameters: `normalModuleFactory` + + +### `contextModuleFactory` + +Runs a plugin after a `ContextModuleFactory` is created. + +Parameters: `contextModuleFactory` + + +### `beforeCompile` + +`AsyncSeriesHook` + +Executes a plugin after compilation parameters are created. + +Parameters: `compilationParams` + + +### `compile` + +`SyncHook` + +Hook into the compiler before a new compilation is created. + +Parameters: `compilationParams` + + +### `thisCompilation` + +`SyncHook` + +Executed before emitting the `compilation` event (see below). + +Parameters: `compilation` + + +### `compilation` + +`SyncHook` + +Runs a plugin after a compilation has been created. + +Parameters: `compilation` + + +### `make` + +`AsyncParallelHook` + +... + +Parameters: `compilation` + + +### `afterCompile` + +`AsyncSeriesHook` + +... + +Parameters: `compilation` + + +### `shouldEmit` + +`SyncBailHook` + +Can return true/false at this point + +Parameters: `compilation` + + +### `emit` + +`AsyncSeriesHook` + +Before emitting assets to output dir + +Parameters: `compilation` + + +### `afterEmit` + +`AsyncSeriesHook` + +After emitting assets to output dir + +Parameters: `compilation` + + +### `done` + +`AsyncSeriesHook` + +Compilation has completed. + +Parameters: `stats` + + +### `failed` + +`SyncHook` + +Compilation has failed. + +Parameters: `error` + + +### `invalid` + +`SyncHook` + +Watch compilation has been invalidated. + +Parameters: `fileName`, `changeTime` + + +### `watchClose` + +`SyncHook` + +Watch mode has stopped. + + +# Introduction + +A variety of interfaces are available to customize the compilation process. +Some features overlap between interfaces, e.g. a configuration option may be +available via a CLI flag, while others exist only through a single interface. +The following high-level information should get you started. + + +## CLI + +The Command Line Interface (CLI) to configure and interact with your build. It +is especially useful in the case of early prototyping and profiling. For the +most part, the CLI is simply used to kick off the process using a configuration +file and a few flags (e.g. `--env`). + +[Learn more about the CLI!](/api/cli) + + +## Module + +When processing modules with webpack, it is important to understand the +different module syntaxes -- specifically the [methods](/api/module-methods) +and [variables](/api/module-variables) -- that are supported. + +[Learn more about modules!](/api/module-methods) + + +## Node + +While most users can get away with just using the CLI along with a +configuration file, more fine-grained control of the compilation can be +achieved via the Node interface. This includes passing multiple configurations, +programmatically running or watching, and collecting stats. + +[Learn more about the Node API!](/api/node) + + +## Loaders + +Loaders are transformations that are applied to the source code of a module. +They are written as functions that accept source code as a parameter and return +a new version of that code with transformations applied. + +[Learn more about loaders!](/api/loaders) + + +## Plugins + +The plugin interface allows users to tap directly into the compilation process. +Plugins can register handlers on lifecycle hooks that run at different points +throughout a compilation. When each hook is executed, the plugin will have full +access to the current state of the compilation. + +[Learn more about plugins!](/api/plugins) + + +# Command Line Interface + +For proper usage and easy distribution of this configuration, webpack can be configured with `webpack.config.js`. Any parameters sent to the CLI will map to a corresponding parameter in the config file. + +Read the [installation guide](/guides/installation) if you don't already have webpack and CLI installed. + + +## Usage with config file + +```sh +webpack [--config webpack.config.js] +``` + +See [configuration](/configuration) for the options in the configuration file. + + +## Usage without config file + +```sh +webpack <entry> [<entry>] -o <output> +``` + +__`<entry>`__ + +A filename or a set of named filenames which act as the entry point to build your project. You can pass multiple entries (every entry is loaded on startup). If you pass a pair in the form `<name>=<request>` you can create an additional entry point. It will be mapped to the configuration option `entry`. + +__`<output>`__ + +A path and filename for the bundled file to be saved in. It will be mapped to the configuration options `output.path` and `output.filename`. + +__Example__ + +If your project structure is as follows - + +```bash +. +├── dist +├── index.html +└── src + ├── index.js + ├── index2.js + └── others.js +``` + +```bash +webpack src/index.js -o dist/bundle.js +``` + +This will bundle your source code with entry as `index.js` and the output bundle file will have a path of `dist` and the filename will be `bundle.js` + +```bash + | Asset | Size | Chunks | Chunk Names | + |-----------|---------|-------------|-------------| + | bundle.js | 1.54 kB | 0 [emitted] | index | + [0] ./src/index.js 51 bytes {0} [built] + [1] ./src/others.js 29 bytes {0} [built] +``` + +```bash +webpack index=./src/index.js entry2=./src/index2.js dist/bundle.js +``` + +This will form the bundle with both the files as separate entry points. + +```bash + | Asset | Size | Chunks | Chunk Names | + |-----------|---------|---------------|---------------| + | bundle.js | 1.55 kB | 0,1 [emitted] | index, entry2 | + [0] ./src/index.js 51 bytes {0} [built] + [0] ./src/index2.js 54 bytes {1} [built] + [1] ./src/others.js 29 bytes {0} {1} [built] +``` + + +### Common Options + +W> Note that Command Line Interface has a higher precedence for the arguments you use it with than your configuration file. For instance, if you pass [`--mode="production"`](/concepts/mode/#usage) to webpack CLI and your configuration file uses `development`, `production` will be used. + +__List all of the options available on the cli__ + +```bash +webpack --help +webpack -h +``` + +__Build source using a config file__ + +Specifies a different [configuration](/configuration) file to pick up. Use this if you want to specify something different than `webpack.config.js`, which is the default. + +```bash +webpack --config example.config.js +``` + +__Print result of webpack as a JSON__ + +```bash +webpack --json +webpack --json > stats.json +``` + +In every other case, webpack prints out a set of stats showing bundle, chunk and timing details. Using this option the output can be a JSON object. This response is accepted by webpack's [analyse tool](https://webpack.github.io/analyse/), or chrisbateman's [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/), or th0r's [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). The analyse tool will take in the JSON and provide all the details of the build in graphical form. + +### Environment Options + +When the webpack configuration [exports a function](/configuration/configuration-types#exporting-a-function), an "environment" may be passed to it. + +```bash +webpack --env.production # sets env.production == true +webpack --env.platform=web # sets env.platform == "web" +``` + +The `--env` argument accepts various syntaxes: + +Invocation | Resulting environment +---------------------------------------- | --------------------------- +`webpack --env prod` | `"prod"` +`webpack --env.prod` | `{ prod: true }` +`webpack --env.prod=1` | `{ prod: 1 }` +`webpack --env.prod=foo` | `{ prod: "foo" }` +`webpack --env.prod --env.min` | `{ prod: true, min: true }` +`webpack --env.prod --env min` | `[{ prod: true }, "min"]` +`webpack --env.prod=foo --env.prod=bar` | `{prod: [ "foo", "bar" ]}` + +T> See the [environment variables](/guides/environment-variables) guide for more information on its usage. + +### Config Options + +Parameter | Explanation | Input type | Default +------------------------- | ------------------------------------------- | ---------- | ------------------ +`--config` | Path to the config file | string | webpack.config.js or webpackfile.js +`--config-register, -r` | Preload one or more modules before loading the webpack configuration | array | +`--config-name` | Name of the config to use | string | +`--env` | Environment passed to the config, when it is a function | | +`--mode` | Mode to use, either "development" or "production" | string | + +### Output Options + +This set of options allows you to manipulate certain [output](/configuration/output) parameters of your build. + +Parameter | Explanation | Input type | Default +------------------------- | ------------------------------------------- | ---------- | ------------------ +`--output-chunk-filename` | The output filename for additional chunks | string | filename with [id] instead of [name] or [id] prefixed +`--output-filename` | The output filename of the bundle | string | [name].js +`--output-jsonp-function` | The name of the JSONP function used for chunk loading | string | webpackJsonp +`--output-library` | Expose the exports of the entry point as library | string | +`--output-library-target` | The type for exposing the exports of the entry point as library | string | var +`--output-path` | The output path for compilation assets | string | Current directory +`--output-pathinfo` | Include a comment with the request for every dependency | boolean | false +`--output-public-path` | The public path for the assets | string | / +`--output-source-map-filename` | The output filename for the SourceMap | string | [name].map or [outputFilename].map +`--build-delimiter` | Display custom text after build output | string | Default string is null. You could provide a string such as `=== Build done ===` + + +#### Example Usage + +```bash +webpack index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' + +| Asset | Size | Chunks | Chunk Names | +|--------------------------------------|---------|-------------|---------------| +| index2740fdca26e9348bedbec.bundle.js | 2.6 kB | 0 [emitted] | index2 | +| index740fdca26e9348bedbec.bundle.js | 2.59 kB | 1 [emitted] | index | + [0] ./src/others.js 29 bytes {0} {1} [built] + [1] ./src/index.js 51 bytes {1} [built] + [2] ./src/index2.js 54 bytes {0} [built] +``` + +```bash +webpack.js index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' --devtool source-map --output-source-map-filename='[name]123.map' + +| Asset | Size | Chunks | Chunk Names | +|--------------------------------------|---------|-------------|---------------| +| index2740fdca26e9348bedbec.bundle.js | 2.76 kB | 0 [emitted] | index2 | +| index740fdca26e9348bedbec.bundle.js | 2.74 kB | 1 [emitted] | index | +| index2123.map | 2.95 kB | 0 [emitted] | index2 | +| index123.map | 2.95 kB | 1 [emitted] | index | + [0] ./src/others.js 29 bytes {0} {1} [built] + [1] ./src/index.js 51 bytes {1} [built] + [2] ./src/index2.js 54 bytes {0} [built] +``` + + +### Debug Options + +This set of options allows you to better debug the application containing assets compiled with webpack + +Parameter | Explanation | Input type | Default value +------------ | ------------------------------------------------ | ---------- | ------------- +`--debug` | Switch loaders to debug mode | boolean | false +`--devtool` | Define [source map type](/configuration/devtool/) for the bundled resources | string | - +`--progress` | Print compilation progress in percentage | boolean | false +`--display-error-details` | Display details about errors | boolean | false + +### Module Options + +These options allow you to bind [modules](/configuration/module/) as allowed by webpack + +Parameter | Explanation | Usage +-------------------- | -------------------------------------- | ---------------- +`--module-bind` | Bind a file extension to a loader | `--module-bind js=babel-loader` +`--module-bind-post` | Bind a file extension to a post loader | +`--module-bind-pre` | Bind a file extension to a pre loader | + + +### Watch Options + +These options makes the build [watch](/configuration/watch/) for changes in files of the dependency graph and perform the build again. + +Parameter | Explanation +------------------------- | ---------------------- +`--watch`, `-w` | Watch the filesystem for changes +`--watch-aggregate-timeout` | Timeout for gathering changes while watching +`--watch-poll` | The polling interval for watching (also enable polling) +`--watch-stdin`, `--stdin` | Exit the process when stdin is closed + + +### Optimize Options + +These options allow you to manipulate optimisations for a production build using webpack + +Parameter | Explanation | Plugin Used +--------------------------- | -------------------------------------------------------|---------------------- +`--optimize-max-chunks` | Try to keep the chunk count below a limit | [LimitChunkCountPlugin](/plugins/limit-chunk-count-plugin) +`--optimize-min-chunk-size` | Try to keep the chunk size above a limit | [MinChunkSizePlugin](/plugins/min-chunk-size-plugin) +`--optimize-minimize` | Minimize javascript and switches loaders to minimizing | [TerserPlugin](/plugins/terser-webpack-plugin/) & [LoaderOptionsPlugin](/plugins/loader-options-plugin/) + + +### Resolve Options + +These allow you to configure the webpack [resolver](/configuration/resolve/) with aliases and extensions. + +Parameter | Explanation | Example +---------------------- | ------------------------------------------------------- | ------------- +`--resolve-alias` | Setup a module alias for resolving | --resolve-alias jquery-plugin=jquery.plugin +`--resolve-extensions` | Setup extensions that should be used to resolve modules | --resolve-extensions .es6 .js .ts +`--resolve-loader-alias` | Minimize javascript and switches loaders to minimizing | + + +### Stats Options + +These options allow webpack to display various [stats](/configuration/stats/) and style them differently in the console output. + +Parameter | Explanation | Type +-------------------------------- | ------------------------------------------------------------------ | ------- +`--color`, `--colors` | Force colors on the console [default: enabled for TTY output only] | boolean +`--no-color`, `--no-colors` | Force no colors on the console | boolean +`--display` | Select [display preset](/configuration/stats) (verbose, detailed, normal, minimal, errors-only, none; since webpack 3.0.0) | string +`--display-cached` | Display also cached modules in the output | boolean +`--display-cached-assets` | Display also cached assets in the output | boolean +`--display-chunks` | Display chunks in the output | boolean +`--display-depth` | Display distance from entry point for each module | boolean +`--display-entrypoints` | Display entry points in the output | boolean +`--display-error-details` | Display details about errors | boolean +`--display-exclude` | Exclude modules in the output | boolean +`--display-max-modules` | Sets the maximum number of visible modules in output | number +`--display-modules` | Display even excluded modules in the output | boolean +`--display-optimization-bailout` | Scope hoisting fallback trigger (since webpack 3.0.0) | boolean +`--display-origins` | Display origins of chunks in the output | boolean +`--display-provided-exports` | Display information about exports provided from modules | boolean +`--display-reasons` | Display reasons about module inclusion in the output | boolean +`--display-used-exports` | Display information about used exports in modules (Tree Shaking) | boolean +`--hide-modules` | Hides info about modules | boolean +`--sort-assets-by` | Sorts the assets list by property in asset | string +`--sort-chunks-by` | Sorts the chunks list by property in chunk | string +`--sort-modules-by` | Sorts the modules list by property in module | string +`--verbose` | Show more details | boolean + + +### Advanced Options + +Parameter | Explanation | Usage +----------------- | ---------------------------------------- | ----- +`--bail` | Abort the compilation on first error | +`--cache` | Enable in memory caching [Enabled by default for watch] | `--cache=false` +`--define` | Define any free variable, see [shimming](/guides/shimming) | `--define process.env.NODE_ENV="'development'"` +`--hot` | Enables [Hot Module Replacement](/concepts/hot-module-replacement) | `--hot=true` +`--labeled-modules` | Enables labeled modules [Uses LabeledModulesPlugin] | +`--plugin` | Load this [plugin](/configuration/plugins/) | +`--prefetch` | Prefetch the particular file | `--prefetch=./files.js` +`--provide` | Provide these modules as globals, see [shimming](/guides/shimming) | `--provide jQuery=jquery` +`--records-input-path` | Path to the records file (reading) | +`--records-output-path` | Path to the records file (writing) | +`--records-path` | Path to the records file | +`--target` | The [targeted](/configuration/target/) execution environment | `--target='node'` + +### Shortcuts + +Shortcut | Replaces +---------|---------------------------- +-d | `--debug --devtool cheap-module-eval-source-map --output-pathinfo` +-p | `--optimize-minimize --define process.env.NODE_ENV="production"`, see [building for production](/guides/production) + +### Profiling + +The `--profile` option captures timing information for each step of the compilation and includes this in the output. + +```bash +webpack --profile + +⋮ +[0] ./src/index.js 90 bytes {0} [built] + factory:22ms building:16ms = 38ms +``` + +For each module, the following details are included in the output as applicable: + +- `factory`: time to collect module metadata (e.g. resolving the filename) +- `building`: time to build the module (e.g. loaders and parsing) +- `dependencies`: time to identify and connect the module’s dependencies + +Paired with `--progress`, `--profile` gives you an in depth idea of which step in the compilation is taking how long. This can help you optimise your build in a more informed manner. + +```bash +webpack --progress --profile + +30ms building modules +1ms sealing +1ms optimizing +0ms basic module optimization +1ms module optimization +1ms advanced module optimization +0ms basic chunk optimization +0ms chunk optimization +1ms advanced chunk optimization +0ms module and chunk tree optimization +1ms module reviving +0ms module order optimization +1ms module id optimization +1ms chunk reviving +0ms chunk order optimization +1ms chunk id optimization +10ms hashing +0ms module assets processing +13ms chunk assets processing +1ms additional chunk assets processing +0ms recording +0ms additional asset processing +26ms chunk asset optimization +1ms asset optimization +6ms emitting +⋮ +``` + + +# Compilation Hooks + +The `Compilation` module is used by the `Compiler` to create new compilations +(or builds). A `compilation` instance has access to all modules and their +dependencies (most of which are circular references). It is the literal +compilation of all the modules in the dependency graph of an application. +During the compilation phase, modules are loaded, sealed, optimized, chunked, +hashed and restored. + +The `Compilation` class also extends `Tapable` and provides the following +lifecycle hooks. They can be tapped the same way as compiler hooks: + +``` js +compilation.hooks.someHook.tap(/* ... */); +``` + +As with the `compiler`, `tapAsync` and `tapPromise` may also be available +depending on the type of hook. + + +### `buildModule` + +`SyncHook` + +Triggered before a module build has started. + +Parameters: `module` + + +### `rebuildModule` + +`SyncHook` + +Fired before rebuilding a module. + +Parameters: `module` + + +### `failedModule` + +`SyncHook` + +Run when a module build has failed. + +Parameters: `module` `error` + + +### `succeedModule` + +`SyncHook` + +Executed when a module has been built successfully. + +Parameters: `module` + + +### `finishModules` + +`SyncHook` + +All modules have been built. + +Parameters: `modules` + + +### `finishRebuildingModule` + +`SyncHook` + +A module has been rebuilt. + +Parameters: `module` + + +### `seal` + +`SyncHook` + +Fired when the compilation stops accepting new modules. + + +### `unseal` + +`SyncHook` + +Fired when a compilation begins accepting new modules. + + +### `optimizeDependenciesBasic` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeDependencies` + +`SyncBailHook` + +Fired at the beginning of dependency optimization. + +Parameters: `modules` + + +### `optimizeDependenciesAdvanced` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `afterOptimizeDependencies` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimize` + +`SyncHook` + +Triggered at the beginning of the optimization phase. + + +### `optimizeModulesBasic` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeModules` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeModulesAdvanced` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `afterOptimizeModules` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimizeChunksBasic` + +`SyncBailHook` + +... + +Parameters: `chunks` + + +### `optimizeChunks` + +`SyncBailHook` + +Optimize the chunks. + +Parameters: `chunks` + + +### `optimizeChunksAdvanced` + +`SyncBailHook` + +... + +Parameters: `chunks` + + +### `afterOptimizeChunks` + +`SyncHook` + +Fired after chunk optimization has completed. + +Parameters: `chunks` + + +### `optimizeTree` + +`AsyncSeriesHook` + +Optimize the dependency tree asynchronously. + +Parameters: `chunks` `modules` + + +### `afterOptimizeTree` + +`SyncHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModulesBasic` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModules` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModulesAdvanced` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `afterOptimizeChunkModules` + +`SyncHook` + +... + +Parameters: `chunks` `modules` + + +### `shouldRecord` + +`SyncBailHook` + +... + + +### `reviveModules` + +`SyncHook` + +Restore module information from records. + +Parameters: `modules` `records` + + +### `optimizeModuleOrder` + +`SyncHook` + +Sort the modules in from most to least important. + +Parameters: `modules` + + +### `advancedOptimizeModuleOrder` + +`SyncHook` + +... + +Parameters: `modules` + + +### `beforeModuleIds` + +`SyncHook` + +... + +Parameters: `modules` + + +### `moduleIds` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimizeModuleIds` + +`SyncHook` + +... + +Parameters: `chunks` + + +### `afterOptimizeModuleIds` + +`SyncHook` + +... + +Parameters: `chunks` + + +### `reviveChunks` + +`SyncHook` + +Restore chunk information from records. + +Parameters: `modules` `records` + + +### `optimizeChunkOrder` + +`SyncHook` + +Sort the chunks in from most to least important. + +Parameters: `chunks` + + +### `beforeOptimizeChunkIds` + +`SyncHook` + +Fired before chunk `id` optimization. + +Parameters: `chunks` + + +### `optimizeChunkIds` + +`SyncHook` + +Optimize the `id` of each chunk. + +Parameters: `chunks` + + +### `afterOptimizeChunkIds` + +`SyncHook` + +Triggered after chunk `id` optimization has finished. + +Parameters: `chunks` + + +### `recordModules` + +`SyncHook` + +Store module info to the records. + +Parameters: `modules` `records` + + +### `recordChunks` + +`SyncHook` + +Store chunk info to the records. + +Parameters: `chunks` `records` + + +### `beforeHash` + +`SyncHook` + +Before the compilation is hashed. + + +### `afterHash` + +`SyncHook` + +After the compilation is hashed. + + +### `recordHash` + +`SyncHook` + +... + +Parameters: `records` + + +### `record` + +`SyncHook` + +Store information about the `compilation` to the `records`. + +Parameters: `compilation` `records` + + +### `beforeModuleAssets` + +`SyncHook` + +... + + +### `shouldGenerateChunkAssets` + +`SyncBailHook` + +... + + +### `beforeChunkAssets` + +`SyncHook` + +Before creating the chunk assets. + + +### `additionalChunkAssets` + +`SyncHook` + +Create additional assets for the chunks. + +Parameters: `chunks` + + +### `records` + +`SyncHook` + +... + +Parameters: `compilation` `records` + + +### `additionalAssets` + +`AsyncSeriesHook` + +Create additional assets for the compilation. This hook can be used to download +an image, for example: + +``` js +compilation.hooks.additionalAssets.tapAsync('MyPlugin', callback => { + download('https://img.shields.io/npm/v/webpack.svg', function(resp) { + if(resp.status === 200) { + compilation.assets['webpack-version.svg'] = toAsset(resp); + callback(); + } else { + callback(new Error('[webpack-example-plugin] Unable to download the image')); + } + }); +}); +``` + + +### `optimizeChunkAssets` + +`AsyncSeriesHook` + +Optimize any chunk assets. The assets are stored in `compilation.assets`. A +`Chunk` has a property `files` which points to all files created by a chunk. +Any additional chunk assets are stored in `compilation.additionalChunkAssets`. + +Parameters: `chunks` + +Here's an example that simply adds a banner to each chunk. + +``` js +compilation.hooks + .optimizeChunkAssets + .tapAsync('MyPlugin', (chunks, callback) => { + chunks.forEach(chunk => { + chunk.files.forEach(file => { + compilation.assets[file] = new ConcatSource( + '\/**Sweet Banner**\/', + '\n', + compilation.assets[file] + ); + }); + }); + + callback(); + }); +``` + + +### `afterOptimizeChunkAssets` + +`SyncHook` + +The chunk assets have been optimized. + +Parameters: `chunks` + +Here's an example plugin from [@boopathi](https://github.com/boopathi) that outputs exactly what went into each chunk. + +``` js +compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', chunks => { + chunks.forEach(chunk => { + console.log({ + id: chunk.id, + name: chunk.name, + includes: chunk.modules.map(module => module.request) + }); + }); +}); +``` + + +### `optimizeAssets` + +`AsyncSeriesHook` + +Optimize all assets stored in `compilation.assets`. + +Parameters: `assets` + + +### `afterOptimizeAssets` + +`SyncHook` + +The assets has been optimized. + +Parameters: `assets` + + +### `needAdditionalSeal` + +`SyncBailHook` + +... + + +### `afterSeal` + +`AsyncSeriesHook` + +... + + +### `chunkHash` + +`SyncHook` + +... + +Parameters: `chunk` `chunkHash` + + +### `moduleAsset` + +`SyncHook` + +An asset from a module was added to the compilation. + +Parameters: `module` `filename` + + +### `chunkAsset` + +`SyncHook` + +An asset from a chunk was added to the compilation. + +Parameters: `chunk` `filename` + + +### `assetPath` + +`SyncWaterfallHook` + +... + +Parameters: `filename` `data` + + +### `needAdditionalPass` + +`SyncBailHook` + +... + + +### `childCompiler` + +`SyncHook` + +... + +Parameters: `childCompiler` `compilerName` `compilerIndex` + + +### `normalModuleLoader` + +`SyncHook` + +The normal module loader is the function that actually loads all the modules +in the module graph (one-by-one). + +Parameters: `loaderContext` `module` + +### `dependencyReference` + +`SyncWaterfallHook` + +`Compilation.hooks.dependencyReference(depRef, dependency, module)` allows to change the references reported by dependencies. + +Parameters: `depRef` `dependency` `module` + + +# Module Methods + +This section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including [ES6](https://en.wikipedia.org/wiki/ECMAScript#6th_Edition_-_ECMAScript_2015), [CommonJS](https://en.wikipedia.org/wiki/CommonJS), and [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition). + +W> While webpack supports multiple module syntaxes, we recommend following a single syntax for consistency and to avoid odd behaviors/bugs. Here's [one example](https://github.com/webpack/webpack.js.org/issues/552) of mixing ES6 and CommonJS, however there are surely others. + + +## ES6 (Recommended) + +Version 2 of webpack supports ES6 module syntax natively, meaning you can use `import` and `export` without a tool like babel to handle this for you. Keep in mind that you will still probably need babel for other ES6+ features. The following methods are supported by webpack: + + +### `import` + +Statically `import` the `export`s of another module. + +``` javascript +import MyModule from './my-module.js'; +import { NamedExport } from './other-module.js'; +``` + +W> The keyword here is __statically__. Normal `import` statement cannot be used dynamically within other logic or contain variables. See the [spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) for more information and `import()` below for dynamic usage. + + +### `export` + +Export anything as a `default` or named export. + +``` javascript +// Named exports +export var Count = 5; +export function Multiply(a, b) { + return a * b; +} + +// Default export +export default { + // Some data... +}; +``` + + +### `import()` + +`import('path/to/module') -> Promise` + +Dynamically load modules. Calls to `import()` are treated as split points, meaning the requested module and it's children are split out into a separate chunk. + +T> The [ES2015 Loader spec](https://whatwg.github.io/loader/) defines `import()` as method to load ES2015 modules dynamically on runtime. + +``` javascript +if ( module.hot ) { + import('lodash').then(_ => { + // Do something with lodash (a.k.a '_')... + }); +} +``` + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +The spec for `import` doesn't allow control over the chunk's name or other properties as "chunks" are only a concept within webpack. Luckily webpack allows some special parameters via comments so as to not break the spec: + +``` js +// Single target +import( + /* webpackChunkName: "my-chunk-name" */ + /* webpackMode: "lazy" */ + 'module' +); + +// Multiple possible targets +import( + /* webpackInclude: /\.json$/ */ + /* webpackExclude: /\.noimport\.json$/ */ + /* webpackChunkName: "my-chunk-name" */ + /* webpackMode: "lazy" */ + `./locale/${language}` +); +``` + +```js +import(/* webpackIgnore: true */ 'ignored-module.js'); +``` + +`webpackIgnore`: Disables dynamic import parsing when set to `true`. + +W> Note that setting `webpackIgnore` to `true` opts out of code splitting. + +`webpackChunkName`: A name for the new chunk. Since webpack 2.6.0, the placeholders `[index]` and `[request]` are supported within the given string to an incremented number or the actual resolved filename respectively. + +`webpackMode`: Since webpack 2.6.0, different modes for resolving dynamic imports can be specified. The following options are supported: + +- `"lazy"` (default): Generates a lazy-loadable chunk for each `import()`ed module. +- `"lazy-once"`: Generates a single lazy-loadable chunk that can satisfy all calls to `import()`. The chunk will be fetched on the first call to `import()`, and subsequent calls to `import()` will use the same network response. Note that this only makes sense in the case of a partially dynamic statement, e.g. ``import(`./locales/${language}.json`)``, where there are multiple module paths that could potentially be requested. +- `"eager"`: Generates no extra chunk. All modules are included in the current chunk and no additional network requests are made. A `Promise` is still returned but is already resolved. In contrast to a static import, the module isn't executed until the call to `import()` is made. +- `"weak"`: Tries to load the module if the module function has already been loaded in some other way (i. e. another chunk imported it or a script containing the module was loaded). A `Promise` is still returned but, only successfully resolves if the chunks are already on the client. If the module is not available, the `Promise` is rejected. A network request will never be performed. This is useful for universal rendering when required chunks are always manually served in initial requests (embedded within the page), but not in cases where app navigation will trigger an import not initially served. + +T> Note that all options can be combined like so `/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */`. This is wrapped in a JavaScript object and executed using [node VM](https://nodejs.org/dist/latest-v8.x/docs/api/vm.html). You do not need to add curly brackets. + +`webpackInclude`: A regular expression that will be matched against during import resolution. Only modules that match __will be bundled__. + +`webpackExclude`: A regular expression that will be matched against during import resolution. Any module that matches __will not be bundled__. + +T> Note that `webpackInclude` and `webpackExclude` options do not interfere with the prefix. eg: `./locale`. + +W> Fully dynamic statements, such as `import(foo)`, __will fail__ because webpack requires at least some file location information. This is because `foo` could potentially be any path to any file in your system or project. The `import()` must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files. + +W> Every module that could potentially be requested on an `import()` call is included. For example, ``import(`./locale/${language}.json`)`` will cause every `.json` file in the `./locale` directory to be bundled into the new chunk. At run time, when the variable `language` has been computed, any file like `english.json` or `german.json` will be available for consumption. Using the `webpackInclude` and `webpackExclude` options allows us to add regex patterns that reduce the files that webpack will bundle for this import. + +W> The use of `System.import` in webpack [did not fit the proposed spec](https://github.com/webpack/webpack/issues/2163), so it was deprecated in webpack [2.1.0-beta.28](https://github.com/webpack/webpack/releases/tag/v2.1.0-beta.28) in favor of `import()`. + + +## CommonJS + +The goal of CommonJS is to specify an ecosystem for JavaScript outside the browser. The following CommonJS methods are supported by webpack: + + +### `require` + +``` javascript +require(dependency: String); +``` + +Synchronously retrieve the exports from another module. The compiler will ensure that the dependency is available in the output bundle. + +``` javascript +var $ = require('jquery'); +var myModule = require('my-module'); +``` + +W> Using it asynchronously may not have the expected effect. + + +### `require.resolve` + +``` javascript +require.resolve(dependency: String); +``` + +Synchronously retrieve a module's ID. The compiler will ensure that the dependency is available in the output bundle. See [`module.id`](/api/module-variables#module-id-commonjs-) for more information. + +W> Module ID is a number in webpack (in contrast to NodeJS where it is a string -- the filename). + + +### `require.cache` + +Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. + +W> This is only needed in rare cases for compatibility! + +``` javascript +var d1 = require('dependency'); +require('dependency') === d1; +delete require.cache[require.resolve('dependency')]; +require('dependency') !== d1; +``` + +``` javascript +// in file.js +require.cache[module.id] === module; +require('./file.js') === module.exports; +delete require.cache[module.id]; +require.cache[module.id] === undefined; +require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow +require.cache[module.id] !== module; +``` + + +### `require.ensure` + +W> `require.ensure()` is specific to webpack and superseded by `import()`. + +<!-- eslint-skip --> + +```js +require.ensure( + dependencies: String[], + callback: function(require), + errorCallback: function(error), + chunkName: String +) +``` + +Split out the given `dependencies` to a separate bundle that that will be loaded asynchronously. When using CommonJS module syntax, this is the only way to dynamically load dependencies. Meaning, this code can be run within execution, only loading the `dependencies` if certain conditions are met. + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `require.ensure` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +``` javascript +var a = require('normal-dep'); + +if ( module.hot ) { + require.ensure(['b'], function(require) { + var c = require('c'); + + // Do something special... + }); +} +``` + +The following parameters are supported in the order specified above: + +- `dependencies`: An array of strings declaring all modules required for the code in the `callback` to execute. +- `callback`: A function that webpack will execute once the dependencies are loaded. An implementation of the `require` function is sent as a parameter to this function. The function body can use this to further `require()` modules it needs for execution. +- `errorCallback`: A function that is executed when webpack fails to load the dependencies. +- `chunkName`: A name given to the chunk created by this particular `require.ensure()`. By passing the same `chunkName` to various `require.ensure()` calls, we can combine their code into a single chunk, resulting in only one bundle that the browser must load. + +W> Although the implementation of `require` is passed as an argument to the `callback` function, using an arbitrary name e.g. `require.ensure([], function(request) { request('someModule'); })` isn't handled by webpack's static parser. Use `require` instead, e.g. `require.ensure([], function(require) { require('someModule'); })`. + + + +## AMD + +Asynchronous Module Definition (AMD) is a JavaScript specification that defines an interface for writing and loading modules. The following AMD methods are supported by webpack: + + +### `define` (with factory) + +<!-- eslint-skip --> + +```js +define([name: String], [dependencies: String[]], factoryMethod: function(...)) +``` + +If `dependencies` are provided, `factoryMethod` will be called with the exports of each dependency (in the same order). If `dependencies` are not provided, `factoryMethod` is called with `require`, `exports` and `module` (for compatibility!). If this function returns a value, this value is exported by the module. The compiler ensures that each dependency is available. + +W> Note that webpack ignores the `name` argument. + +``` javascript +define(['jquery', 'my-module'], function($, myModule) { + // Do something with $ and myModule... + + // Export a function + return function doSomething() { + // ... + }; +}); +``` + +W> This CANNOT be used in an asynchronous function. + + +### `define` (with value) + +<!-- eslint-skip --> + +```js +define(value: !Function) +``` + +This will simply export the provided `value`. The `value` here can be anything except a function. + +``` javascript +define({ + answer: 42 +}); +``` + +W> This CANNOT be used in an async function. + + +### `require` (amd-version) + +<!-- eslint-skip --> + +```js +require(dependencies: String[], [callback: function(...)]) +``` + +Similar to `require.ensure`, this will split the given `dependencies` into a separate bundle that will be loaded asynchronously. The `callback` will be called with the exports of each dependency in the `dependencies` array. + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use AMD with older browsers (e.g. Internet Explorer 11), remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +``` javascript +require(['b'], function(b) { + var c = require('c'); +}); +``` + +W> There is no option to provide a chunk name. + + + +## Labeled Modules + +The internal `LabeledModulesPlugin` enables you to use the following methods for exporting and requiring within your modules: + + +### `export` label + +Export the given `value`. The label can occur before a function declaration or a variable declaration. The function name or variable name is the identifier under which the value is exported. + +<!-- eslint-skip --> + +```js +export: var answer = 42; +export: function method(value) { + // Do something... +}; +``` + +W> Using it in an async function may not have the expected effect. + + +### `require` label + +Make all exports from the dependency available in the current scope. The `require` label can occur before a string. The dependency must export values with the `export` label. CommonJS or AMD modules cannot be consumed. + +__some-dependency.js__ + +<!-- eslint-skip --> + +```js +export: var answer = 42; +export: function method(value) { + // Do something... +}; +``` + +<!-- eslint-skip --> + +```js +require: 'some-dependency'; +console.log(answer); +method(...); +``` + + + +## Webpack + +Aside from the module syntaxes described above, webpack also allows a few custom, webpack-specific methods: + + +### `require.context` + +<!-- eslint-skip --> + +```js +require.context( + directory: String, + includeSubdirs: Boolean /* optional, default true */, + filter: RegExp /* optional, default /^\.\/.*$/, any file */, + mode: String /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */ +) +``` + +Specify a whole group of dependencies using a path to the `directory`, an option to `includeSubdirs`, a `filter` for more fine grained control of the modules included, and a `mode` to define the way how loading will work. Underlying modules can then be easily resolved later on: + +```javascript +var context = require.context('components', true, /\.html$/); +var componentA = context.resolve('componentA'); +``` + +If `mode` is specified as "lazy", the underlying modules will be loaded asynchronously: + +```javascript +var context = require.context('locales', true, /\.json$/, 'lazy'); +context('localeA').then(locale => { + // do something with locale +}); +``` + +The full list of available modes and its behavior is described in [`import()`](#import-) documentation. + +### `require.include` + +<!-- eslint-skip --> + +```js +require.include(dependency: String) +``` + +Include a `dependency` without executing it. This can be used for optimizing the position of a module in the output chunks. + +``` javascript +require.include('a'); +require.ensure(['a', 'b'], function(require) { /* ... */ }); +require.ensure(['a', 'c'], function(require) { /* ... */ }); +``` + +This will result in following output: + +- entry chunk: `file.js` and `a` +- anonymous chunk: `b` +- anonymous chunk: `c` + +Without `require.include('a')` it would be duplicated in both anonymous chunks. + + +### `require.resolveWeak` + +Similar to `require.resolve`, but this won't pull the `module` into the bundle. It's what is considered a "weak" dependency. + +``` javascript +if(__webpack_modules__[require.resolveWeak('module')]) { + // Do something when module is available... +} +if(require.cache[require.resolveWeak('module')]) { + // Do something when module was loaded before... +} + +// You can perform dynamic resolves ("context") +// just as with other require/import methods. +const page = 'Foo'; +__webpack_modules__[require.resolveWeak(`./page/${page}`)]; +``` + +T> `require.resolveWeak` is the foundation of _universal rendering_ (SSR + Code Splitting), as used in packages such as [react-universal-component](https://github.com/faceyspacey/react-universal-component). It allows code to render synchronously on both the server and initial page-loads on the client. It requires that chunks are manually served or somehow available. It's able to require modules without indicating they should be bundled into a chunk. It's used in conjunction with `import()` which takes over when user navigation triggers additional imports. + + +# Node.js API + +webpack provides a Node.js API which can be used directly in Node.js runtime. + +The Node.js API is useful in scenarios in which you need to customize the build or development process since all the reporting and error handling must be done manually and webpack only does the compiling part. For this reason the [`stats`](/configuration/stats) configuration options will not have any effect in the `webpack()` call. + + +## Installation + +To start using webpack Node.js API, first install webpack if you haven’t yet: + +``` bash +npm install --save-dev webpack +``` + +Then require the webpack module in your Node.js script: + +``` js +const webpack = require('webpack'); +``` + +Or if you prefer ES2015: + +``` js +import webpack from 'webpack'; +``` + + +## `webpack()` + +The imported `webpack` function is fed a webpack [Configuration Object](/configuration/) and runs the webpack compiler if a callback function is provided: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, [stats](#stats-object)) => { + if (err || stats.hasErrors()) { + // [Handle errors here](#error-handling) + } + // Done processing +}); +``` + +T> The `err` object __will not__ include compilation errors and those must be handled separately using `stats.hasErrors()` which will be covered in detail in [Error Handling](#error-handling) section of this guide. The `err` object will only contain webpack-related issues, such as misconfiguration, etc. + +T> You can provide the `webpack` function with an array of configurations. See +the [MultiCompiler](#multicompiler) section below for more information. + + +## Compiler Instance + +If you don’t pass the `webpack` runner function a callback, it will return a +webpack `Compiler` instance. This instance can be used to manually trigger the +webpack runner or have it build and watch for changes, much like the +[CLI](/api/cli/). The `Compiler` instance provides the following methods: + +- `.run(callback)` +- `.watch(watchOptions, handler)` + +Typically, only one master `Compiler` instance is created, although child +compilers can be created in order to delegate specific tasks. The `Compiler` is +ultimately just a function which performs bare minimum functionality to keep a +lifecycle running. It delegates all the loading, bundling, and writing work to +registered plugins. + +The `hooks` property on a `Compiler` instance is used to register a plugin to +any hook event in the `Compiler`'s lifecycle. The +[`WebpackOptionsDefaulter`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js) +and [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js) +utilities are used by webpack to configure its `Compiler` instance with all the +built-in plugins. + +The `run` method is then used to kickstart all compilation work. Upon +completion, the given `callback` function is executed. The final logging of +stats and errors should be done in this `callback` function. + +W> The API only supports a single concurrent compilation at a time. When using +`run`, wait for it to finish before calling `run` or `watch` again. When using +`watch`, call `close` and wait for it to finish before calling `run` or `watch` +again. Concurrent compilations will corrupt the output files. + + +## Run + +Calling the `run` method on the `Compiler` instance is much like the quick run +method mentioned above: + +``` js-with-links +const webpack = require("webpack"); + +const compiler = webpack({ + // [Configuration Object](/configuration/) +}); + +compiler.run((err, [stats](#stats-object)) => { + // ... +}); +``` + + +## Watching + +Calling the `watch` method, triggers the webpack runner, but then watches for +changes (much like CLI: `webpack --watch`), as soon as webpack detects a +change, runs again. Returns an instance of `Watching`. + +``` js +watch(watchOptions, callback); +``` + +``` js-with-links +const webpack = require("webpack"); + +const compiler = webpack({ + // [Configuration Object](/configuration/) +}); + +const watching = compiler.watch({ + // Example [watchOptions](/configuration/watch/#watchoptions) + aggregateTimeout: 300, + poll: undefined +}, (err, [stats](#stats-object)) => { + // Print watch/build result here... + console.log(stats); +}); +``` + +`Watching` options are covered in detail +[here](/configuration/watch/#watchoptions). + +W> Filesystem inaccuracies may trigger multiple builds for a single change. So, +in the example above, the `console.log` statement may fire multiple times for a +single modification. Users should expect this behavior and may check +`stats.hash` to see if the file hash has actually changed. + + +### Close `Watching` + +The `watch` method returns a `Watching` instance that exposes +`.close(callback)` method. Calling this method will end watching: + +``` js +watching.close(() => { + console.log('Watching Ended.'); +}); +``` + +W> It’s not allowed to watch or run again before the existing watcher has been +closed or invalidated. + + +### Invalidate `Watching` + +Using `watching.invalidate`, you can manually invalidate the current compiling +round, without stopping the watch process: + +``` js +watching.invalidate(); +``` + + +## Stats Object + +The `stats` object that is passed as a second argument of the +[`webpack()`](#webpack-) callback, is a good source of information about the +code compilation process. It includes: + +- Errors and Warnings (if any) +- Timings +- Module and Chunk information + +The [webpack CLI](/api/cli) uses this information to display nicely formatted +output in your console. + +T> When using the [`MultiCompiler`](/api/plugins/compiler#multicompiler), a +`MultiStats` instance is returned that fulfills the same interface as `stats`, +i.e. the methods described below. + +This `stats` object exposes the following methods: + + +### `stats.hasErrors()` + +Can be used to check if there were errors while compiling. Returns `true` or +`false`. + + +### `stats.hasWarnings()` + +Can be used to check if there were warnings while compiling. Returns `true` or +`false`. + + +### `stats.toJson(options)` + +Returns compilation information as a JSON object. `options` can be either a +string (a preset) or an object for more granular control: + +``` js-with-links +stats.toJson("minimal"); // [more options: "verbose", etc](/configuration/stats). +``` + +``` js +stats.toJson({ + assets: false, + hash: true +}); +``` + +All available options and presets are described in the stats [documentation](/configuration/stats). + +> Here’s an [example] +(https://github.com/webpack/analyse/blob/master/app/pages/upload/example.json) +of this function’s output. + + +### `stats.toString(options)` + +Returns a formatted string of the compilation information (similar to +[CLI](/api/cli) output). + +Options are the same as [`stats.toJson(options)`](/api/node#stats-tojson-options-) with one addition: + +``` js +stats.toString({ + // Add console colors + colors: true +}); +``` + +Here’s an example of `stats.toString()` usage: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, stats) => { + if (err) { + console.error(err); + return; + } + + console.log(stats.toString({ + chunks: false, // Makes the build much quieter + colors: true // Shows colors in the console + })); +}); +``` + + +## MultiCompiler + +The `MultiCompiler` module allows webpack to run multiple configurations in +separate compilers. If the `options` parameter in the webpack's NodeJS api is +an array of options, webpack applies separate compilers and calls the +`callback` method at the end of each compiler execution. + +``` js-with-links +var webpack = require('webpack'); + +webpack([ + { entry: './index1.js', output: { filename: 'bundle1.js' } }, + { entry: './index2.js', output: { filename: 'bundle2.js' } } +], (err, [stats](#stats-object)) => { + process.stdout.write(stats.toString() + "\n"); +}) +``` + +W> Multiple configurations will __not be run in parallel__. Each +configuration is only processed after the previous one has finished +processing. To process them in parallel, you can use a third-party solution +like [parallel-webpack](https://www.npmjs.com/package/parallel-webpack). + + +## Error Handling + +For a good error handling, you need to account for these three types of errors: + +- Fatal webpack errors (wrong configuration, etc) +- Compilation errors (missing modules, syntax errors, etc) +- Compilation warnings + +Here’s an example that does all that: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, stats) => { + if (err) { + console.error(err.stack || err); + if (err.details) { + console.error(err.details); + } + return; + } + + const info = stats.toJson(); + + if (stats.hasErrors()) { + console.error(info.errors); + } + + if (stats.hasWarnings()) { + console.warn(info.warnings); + } + + // Log result... +}); +``` + + +## Custom File Systems + +By default, webpack reads files and writes files to disk using a normal file +system. However, it is possible to change the input or output behavior using a +different kind of file system (memory, webDAV, etc). To accomplish this, one +can change the `inputFileSystem` or `outputFileSystem`. For example, you can +replace the default `outputFileSystem` with +[`memory-fs`](https://github.com/webpack/memory-fs) to write files to memory +instead of to disk: + +``` js +const MemoryFS = require('memory-fs'); +const webpack = require('webpack'); + +const fs = new MemoryFS(); +const compiler = webpack({ /* options*/ }); + +compiler.outputFileSystem = fs; +compiler.run((err, stats) => { + // Read the output later: + const content = fs.readFileSync('...'); +}); +``` + +Note that this is what +[webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware), +used by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) +and many other packages, uses to mysteriously hide your files but continue +serving them up to the browser! + +T> The output file system you provide needs to be compatible with Node’s own +[`fs`](https://nodejs.org/api/fs.html) interface, which requires the `mkdirp` +and `join` helper methods. + + +# Resolvers + +Resolvers are created using the `enhanced-resolve` package. The `Resolver` +class extends the `tapable` class and uses `tapable` to provide a few hooks. +The `enhanced-resolve` package can be used directly to create new resolvers, +however any [`compiler` instance](/api/node/#compiler-instance) has a few resolver instances that can be +tapped into. + +Before reading on, make sure you at least skim through the +[`enhanced-resolve`](https://github.com/webpack/enhanced-resolve) and [`tapable`](/api/plugins/#tapable) documentation. + + +## Types + +There are three types of built-in resolvers available on the `compiler` class: + +- Normal: Resolves a module via an absolute or relative path. +- Context: Resolves a module within a given context. +- Loader: Resolves a webpack [loader](/loaders). + +Depending on need, any one of these built-in resolver used by the `compiler` +can be customized via plugins as such: + +``` js +compiler.resolverFactory.plugin('resolver [type]', resolver => { + resolver.hooks.resolve.tapAsync('MyPlugin', params => { + // ... + }); +}); +``` + +Where `[type]` is one of the three resolvers mention above, specified as: + +- `normal` +- `context` +- `loader` + + +See the `enhanced-resolve` [documentation](https://github.com/webpack/enhanced-resolve) for a full list of hooks and +descriptions. + + +## Configuration Options + +The resolvers mentioned above can also be customized via a configuration file +with the [`resolve`](/configuration/resolve/) or [`resolveLoader`](/configuration/resolve/#resolveloader) options. These options allow +users to change the resolving behavior through a variety of options including +through resolve `plugins`. + +The resolver plugins, e.g. [`DirectoryNamedPlugin`](https://github.com/shaketbaby/directory-named-webpack-plugin), can be included +directly in `resolve.plugins` rather than using standard plugins. Note that the +`resolve` configuration affects the `normal` and `context` resolvers while +`resolveLoader` is used to modify the `loader` resolver. + + +# Stats Data + +When compiling source code with webpack, users can generate a JSON file containing statistics about modules. These statistics can be used to analyze an application's dependency graph as well as to optimize compilation speed. The file is typically generated with the following CLI command: + +``` bash +webpack --profile --json > compilation-stats.json +``` + +The `--json > compilation-stats.json` flag indicates to webpack that it should emit the `compilation-stats.json` containing the dependency graph and various other build information. Typically, the `--profile` flag is also added so that a `profile` section is added to each [`modules` object](#module-objects) containing module-specific compilation stats. + + +## Structure + +The top-level structure of the output JSON file is fairly straightforward but there are a few nested data structures as well. Each nested structure has a dedicated section below to make this document more consumable. Note that you can click links within the top-level structure below to jump to relevant sections and documentation: + +```js-with-links +{ + "version": "1.4.13", // Version of webpack used for the compilation + "hash": "11593e3b3ac85436984a", // Compilation specific hash + "time": 2469, // Compilation time in milliseconds + "filteredModules": 0, // A count of excluded modules when [`exclude`](/configuration/stats/#stats) is passed to the [`toJson`](/api/node/#stats-tojson-options-) method + "outputPath": "/", // path to webpack output directory + "assetsByChunkName": { + // Chunk name to emitted asset(s) mapping + "main": "web.js?h=11593e3b3ac85436984a", + "named-chunk": "named-chunk.web.js", + "other-chunk": [ + "other-chunk.js", + "other-chunk.css" + ] + }, + "assets": [ + // A list of [asset objects](#asset-objects) + ], + "chunks": [ + // A list of [chunk objects](#chunk-objects) + ], + "modules": [ + // A list of [module objects](#module-objects) + ], + "errors": [ + // A list of [error strings](#errors-and-warnings) + ], + "warnings": [ + // A list of [warning strings](#errors-and-warnings) + ] +} +``` + + +### Asset Objects + +Each `assets` object represents an `output` file emitted from the compilation. They all follow a similar structure: + +<!-- eslint-skip --> + +```js +{ + "chunkNames": [], // The chunks this asset contains + "chunks": [ 10, 6 ], // The chunk IDs this asset contains + "emitted": true, // Indicates whether or not the asset made it to the `output` directory + "name": "10.web.js", // The `output` filename + "size": 1058 // The size of the file in bytes +} +``` + + +### Chunk Objects + +Each `chunks` object represents a group of modules known as a [chunk](/glossary#c). Each object follows the following structure: + +```js-with-links +{ + "entry": true, // Indicates whether or not the chunk contains the webpack runtime + "files": [ + // An array of filename strings that contain this chunk + ], + "filteredModules": 0, // See the description in the [top-level structure](#structure) above + "id": 0, // The ID of this chunk + "initial": true, // Indicates whether this chunk is loaded on initial page load or [on demand](/guides/lazy-loading) + "modules": [ + // A list of [module objects](#module-objects) + "web.js?h=11593e3b3ac85436984a" + ], + "names": [ + // An list of chunk names contained within this chunk + ], + "origins": [ + // See the description below... + ], + "parents": [], // Parent chunk IDs + "rendered": true, // Indicates whether or not the chunk went through Code Generation + "size": 188057 // Chunk size in bytes +} +``` + +The `chunks` object will also contain a list of `origins` describing how the given chunk originated. Each `origins` object follows the following schema: + +```js-with-links +{ + "loc": "", // Lines of code that generated this chunk + "module": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleId": 0, // The ID of the module + "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleName": "./lib/index.web.js", // Relative path to the module + "name": "main", // The name of the chunk + "reasons": [ + // A list of the same `reasons` found in [module objects](#module-objects) + ] +} +``` + + +### Module Objects + +What good would these statistics be without some description of the compiled application's actual modules? Each module in the dependency graph is represented by the following structure: + +```js-with-links +{ + "assets": [ + // A list of [asset objects](#asset-objects) + ], + "built": true, // Indicates that the module went through [Loaders](/concepts/loaders), Parsing, and Code Generation + "cacheable": true, // Whether or not this module is cacheable + "chunks": [ + // IDs of chunks that contain this module + ], + "errors": 0, // Number of errors when resolving or processing the module + "failed": false, // Whether or not compilation failed on this module + "id": 0, // The ID of the module (analagous to [`module.id`](/api/module-variables#module-id-commonjs-)) + "identifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // A unique ID used internally + "name": "./lib/index.web.js", // Path to the actual file + "optional": false, // All requests to this module are with `try... catch` blocks (irrelevant with ESM) + "prefetched": false, // Indicates whether or not the module was [prefetched](/plugins/prefetch-plugin) + "profile": { + // Module specific compilation stats corresponding to the [`--profile` flag](/api/cli#profiling) (in milliseconds) + "building": 73, // Loading and parsing + "dependencies": 242, // Building dependencies + "factory": 11 // Resolving dependencies + }, + "reasons": [ + // See the description below... + ], + "size": 3593, // Estimated size of the module in bytes + "source": "// Should not break it...\r\nif(typeof...", // The stringified raw source + "warnings": 0 // Number of warnings when resolving or processing the module +} +``` + +Every module also contains a list of `reasons` objects describing why that module was included in the dependency graph. Each "reason" is similar to the `origins` seen above in the [chunk objects](#chunk-objects) section: + +```js-with-links +{ + "loc": "33:24-93", // Lines of code that caused the module to be included + "module": "./lib/index.web.js", // Relative path to the module based on [context](/configuration/entry-context/#context) + "moduleId": 0, // The ID of the module + "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleName": "./lib/index.web.js", // A more readable name for the module (used for "pretty-printing") + "type": "require.context", // The [type of request](/api/module-methods) used + "userRequest": "../../cases" // Raw string used for the `import` or `require` request +} +``` + + +### Errors and Warnings + +The `errors` and `warnings` properties each contain a list of strings. Each string contains a message and stack trace: + +``` bash +../cases/parsing/browserify/index.js +Critical dependencies: +2:114-121 This seem to be a pre-built javascript file. Even while this is possible, it's not recommended. Try to require to original source to get better results. + @ ../cases/parsing/browserify/index.js 2:114-121 +``` + +W> Note that the stack traces are removed when `errorDetails: false` is passed to the `toJson` method. The `errorDetails` option is set to `true` by default. + + +# Loader API + +A loader is just a JavaScript module that exports a function. The [loader runner](https://github.com/webpack/loader-runner) calls this function and passes the result of the previous loader or the resource file into it. The `this` context of the function is filled-in by webpack and the [loader runner](https://github.com/webpack/loader-runner) with some useful methods that allow the loader (among other things) to change its invocation style to async, or get query parameters. + +The first loader is passed one argument: the content of the resource file. The compiler expects a result from the last loader. The result should be a `String` or a `Buffer` (which is converted to a string), representing the JavaScript source code of the module. An optional SourceMap result (as JSON object) may also be passed. + +A single result can be returned in __sync mode__. For multiple results the `this.callback()` must be called. In __async mode__ `this.async()` must be called to indicate that the [loader runner](https://github.com/webpack/loader-runner) should wait for an asynchronous result. It returns `this.callback()`. Then the loader must return `undefined` and call that callback. + + +## Examples + +The following sections provide some basic examples of the different types of loaders. Note that the `map` and `meta` parameters are optional, see [`this.callback`](/api/loaders#this-callback) below. + +### Synchronous Loaders + +Either `return` or `this.callback` can be used to return the transformed `content` synchronously: + +__sync-loader.js__ + +``` js +module.exports = function(content, map, meta) { + return someSyncOperation(content); +}; +``` + +The `this.callback` method is more flexible as it allows multiple arguments to be passed as opposed to just the `content`. + +__sync-loader-with-multiple-results.js__ + +``` js +module.exports = function(content, map, meta) { + this.callback(null, someSyncOperation(content), map, meta); + return; // always return undefined when calling callback() +}; +``` + +### Asynchronous Loaders + +For asynchronous loaders, [`this.async`](/api/loaders#this-async) is used to retrieve the `callback` function: + +__async-loader.js__ + +``` js +module.exports = function(content, map, meta) { + var callback = this.async(); + someAsyncOperation(content, function(err, result) { + if (err) return callback(err); + callback(null, result, map, meta); + }); +}; +``` + +__async-loader-with-multiple-results.js__ + +``` js +module.exports = function(content, map, meta) { + var callback = this.async(); + someAsyncOperation(content, function(err, result, sourceMaps, meta) { + if (err) return callback(err); + callback(null, result, sourceMaps, meta); + }); +}; +``` + +T> Loaders were originally designed to work in synchronous loader pipelines, like Node.js (using [enhanced-require](https://github.com/webpack/enhanced-require)), _and_ asynchronous pipelines, like in webpack. However, since expensive synchronous computations are a bad idea in a single-threaded environment like Node.js, we advise to make your loader asynchronously if possible. Synchronous loaders are ok if the amount of computation is trivial. + + +### "Raw" Loader + +By default, the resource file is converted to a UTF-8 string and passed to the loader. By setting the `raw` flag, the loader will receive the raw `Buffer`. Every loader is allowed to deliver its result as `String` or as `Buffer`. The compiler converts them between loaders. + +__raw-loader.js__ + +``` js +module.exports = function(content) { + assert(content instanceof Buffer); + return someSyncOperation(content); + // return value can be a `Buffer` too + // This is also allowed if loader is not "raw" +}; +module.exports.raw = true; +``` + + +### Pitching Loader + +Loaders are __always__ called from right to left. There are some instances where the loader only cares about the __metadata__ behind a request and can ignore the results of the previous loader. The `pitch` method on loaders is called from __left to right__ before the loaders are actually executed (from right to left). For the following [`use`](/configuration/module#rule-use) configuration: + +``` js +module.exports = { + //... + module: { + rules: [ + { + //... + use: [ + 'a-loader', + 'b-loader', + 'c-loader' + ] + } + ] + } +}; +``` + +These steps would occur: + +``` diff +|- a-loader `pitch` + |- b-loader `pitch` + |- c-loader `pitch` + |- requested module is picked up as a dependency + |- c-loader normal execution + |- b-loader normal execution +|- a-loader normal execution +``` + +So why might a loader take advantage of the "pitching" phase? + +First, the `data` passed to the `pitch` method is exposed in the execution phase as well under `this.data` and could be useful for capturing and sharing information from earlier in the cycle. + +``` js +module.exports = function(content) { + return someSyncOperation(content, this.data.value); +}; + +module.exports.pitch = function(remainingRequest, precedingRequest, data) { + data.value = 42; +}; +``` + +Second, if a loader delivers a result in the `pitch` method the process turns around and skips the remaining loaders. In our example above, if the `b-loader`s `pitch` method returned something: + +``` js +module.exports = function(content) { + return someSyncOperation(content); +}; + +module.exports.pitch = function(remainingRequest, precedingRequest, data) { + if (someCondition()) { + return 'module.exports = require(' + JSON.stringify('-!' + remainingRequest) + ');'; + } +}; +``` + +The steps above would be shortened to: + +``` diff +|- a-loader `pitch` + |- b-loader `pitch` returns a module +|- a-loader normal execution +``` + +See the [bundle-loader](https://github.com/webpack-contrib/bundle-loader) for a good example of how this process can be used in a more meaningful way. + + +## The Loader Context + +The loader context represents the properties that are available inside of a loader assigned to the `this` property. + +Given the following example this require call is used: +In `/abc/file.js`: + +``` js +require('./loader1?xyz!loader2!./resource?rrr'); +``` + + +### `this.version` + +__Loader API version.__ Currently `2`. This is useful for providing backwards compatibility. Using the version you can specify custom logic or fallbacks for breaking changes. + + +### `this.context` + +__The directory of the module.__ Can be used as context for resolving other stuff. + +In the example: `/abc` because `resource.js` is in this directory + + +### `this.rootContext` + +Starting with webpack 4, the formerly `this.options.context` is provided as `this.rootContext`. + + +### `this.request` + +The resolved request string. + +In the example: `"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"` + + +### `this.query` + +1. If the loader was configured with an [`options`](/configuration/module/#useentry) object, this will point to that object. +2. If the loader has no `options`, but was invoked with a query string, this will be a string starting with `?`. + +T> Use the [`getOptions` method](https://github.com/webpack/loader-utils#getoptions) from `loader-utils` to extract given loader options. + + +### `this.callback` + +A function that can be called synchronously or asynchronously in order to return multiple results. The expected arguments are: + +<!-- eslint-skip --> + +```js +this.callback( + err: Error | null, + content: string | Buffer, + sourceMap?: SourceMap, + meta?: any +); +``` + +1. The first argument must be an `Error` or `null` +2. The second argument a `string` or a [`Buffer`](https://nodejs.org/api/buffer.html). +3. Optional: The third argument must be a source map that is parsable by [this module](https://github.com/mozilla/source-map). +4. Optional: The fourth option, ignored by webpack, can be anything (e.g. some meta data). + +T> It can be useful to pass an abstract syntax tree (AST), like [`ESTree`](https://github.com/estree/estree), as the fourth argument (`meta`) to speed up the build time if you want to share common ASTs between loaders. + +In case this function is called, you should return undefined to avoid ambiguous loader results. + + +### `this.async` + +Tells the [loader-runner](https://github.com/webpack/loader-runner) that the loader intends to call back asynchronously. Returns `this.callback`. + + +### `this.data` + +A data object shared between the pitch and the normal phase. + + +### `this.cacheable` + +A function that sets the cacheable flag: + +``` typescript +cacheable(flag = true: boolean) +``` + +By default, loader results are flagged as cacheable. Call this method passing `false` to make the loader's result not cacheable. + +A cacheable loader must have a deterministic result, when inputs and dependencies haven't changed. This means the loader shouldn't have other dependencies than specified with `this.addDependency`. + + +### `this.loaders` + +An array of all the loaders. It is writeable in the pitch phase. + +<!-- eslint-skip --> + +```js +loaders = [{request: string, path: string, query: string, module: function}] +``` + +In the example: + +``` js +[ + { + request: '/abc/loader1.js?xyz', + path: '/abc/loader1.js', + query: '?xyz', + module: [Function] + }, + { + request: '/abc/node_modules/loader2/index.js', + path: '/abc/node_modules/loader2/index.js', + query: '', + module: [Function] + } +]; +``` + + +### `this.loaderIndex` + +The index in the loaders array of the current loader. + +In the example: in loader1: `0`, in loader2: `1` + + +### `this.resource` + +The resource part of the request, including query. + +In the example: `"/abc/resource.js?rrr"` + + +### `this.resourcePath` + +The resource file. + +In the example: `"/abc/resource.js"` + + +### `this.resourceQuery` + +The query of the resource. + +In the example: `"?rrr"` + + +### `this.target` + +Target of compilation. Passed from configuration options. + +Example values: `"web"`, `"node"` + + +### `this.webpack` + +This boolean is set to true when this is compiled by webpack. + +T> Loaders were originally designed to also work as Babel transforms. Therefore if you write a loader that works for both, you can use this property to know if there is access to additional loaderContext and webpack features. + + +### `this.sourceMap` + +Should a source map be generated. Since generating source maps can be an expensive task, you should check if source maps are actually requested. + + +### `this.emitWarning` + +``` typescript +emitWarning(warning: Error) +``` + +Emit a warning. + + +### `this.emitError` + +``` typescript +emitError(error: Error) +``` + +Emit an error. + + +### `this.loadModule` + +``` typescript +loadModule(request: string, callback: function(err, source, sourceMap, module)) +``` + +Resolves the given request to a module, applies all configured loaders and calls back with the generated source, the sourceMap and the module instance (usually an instance of [`NormalModule`](https://github.com/webpack/webpack/blob/master/lib/NormalModule.js)). Use this function if you need to know the source code of another module to generate the result. + + +### `this.resolve` + +``` typescript +resolve(context: string, request: string, callback: function(err, result: string)) +``` + +Resolve a request like a require expression. + + +### `this.addDependency` + +``` typescript +addDependency(file: string) +dependency(file: string) // shortcut +``` + +Adds a file as dependency of the loader result in order to make them watchable. For example, [`html-loader`](https://github.com/webpack-contrib/html-loader) uses this technique as it finds `src` and `src-set` attributes. Then, it sets the url's for those attributes as dependencies of the html file that is parsed. + + +### `this.addContextDependency` + +``` typescript +addContextDependency(directory: string) +``` + +Add a directory as dependency of the loader result. + + +### `this.clearDependencies` + +``` typescript +clearDependencies() +``` + +Remove all dependencies of the loader result. Even initial dependencies and these of other loaders. Consider using `pitch`. + + +### `this.emitFile` + +``` typescript +emitFile(name: string, content: Buffer|string, sourceMap: {...}) +``` + +Emit a file. This is webpack-specific. + + +### `this.fs` + +Access to the `compilation`'s `inputFileSystem` property. + + +## Deprecated context properties + +W> The usage of these properties is highly discouraged since we are planning to remove them from the context. They are still listed here for documentation purposes. + + +### `this.exec` + +``` typescript +exec(code: string, filename: string) +``` + +Execute some code fragment like a module. See [this comment](https://github.com/webpack/webpack.js.org/issues/1268#issuecomment-313513988) for a replacement method if needed. + + +### `this.resolveSync` + +``` typescript +resolveSync(context: string, request: string) -> string +``` + +Resolve a request like a require expression. + + +### `this.value` + +Pass values to the next loader. If you know what your result exports if executed as module, set this value here (as a only element array). + + +### `this.inputValue` + +Passed from the last loader. If you would execute the input argument as module, consider reading this variable for a shortcut (for performance). + + +### `this.options` + +W> The `options` property has been deprecated in webpack 3 and removed in webpack 4. + + +### `this.debug` + +A boolean flag. It is set when in debug mode. + + +### `this.minimize` + +Should the result be minimized. + + +### `this._compilation` + +Hacky access to the Compilation object of webpack. + + +### `this._compiler` + +Hacky access to the Compiler object of webpack. + + +### `this._module` + +Hacky access to the Module object being loaded. + + +# Module Variables + +This section covers all __variables__ available in code compiled with webpack. Modules will have access to certain data from the compilation process through `module` and other variables. + + +### `module.loaded` (NodeJS) + +This is `false` if the module is currently executing, and `true` if the sync execution has finished. + + +### `module.hot` (webpack-specific) + +Indicates whether or not [Hot Module Replacement](/concepts/hot-module-replacement) is enabled and provides an interface to the process. See the [HMR API page](/api/hot-module-replacement) for details. + + +### `module.id` (CommonJS) + +The ID of the current module. + +``` javascript +module.id === require.resolve('./file.js'); +``` + + +### `module.exports` (CommonJS) + +Defines the value that will be returned when a consumer makes a `require` call to the module (defaults to a new object). + +``` javascript +module.exports = function doSomething() { + // Do something... +}; +``` + +W> This CANNOT be used in an asynchronous function. + + +### `exports` (CommonJS) + +This variable is equal to default value of `module.exports` (i.e. an object). If `module.exports` gets overwritten, `exports` will no longer be exported. + +``` javascript +exports.someValue = 42; +exports.anObject = { + x: 123 +}; +exports.aFunction = function doSomething() { + // Do something +}; +``` + + +### `global` (NodeJS) + +See [node.js global](https://nodejs.org/api/globals.html#globals_global). + + +### `process` (NodeJS) + +See [node.js process](https://nodejs.org/api/process.html). + + +### `__dirname` (NodeJS) + +Depending on the config option `node.__dirname`: + +- `false`: Not defined +- `mock`: equal "/" +- `true`: [node.js __dirname](https://nodejs.org/api/globals.html#globals_dirname) + +If used inside a expression that is parsed by the Parser, the config option is treated as `true`. + + +### `__filename` (NodeJS) + +Depending on the config option `node.__filename`: + +- `false`: Not defined +- `mock`: equal "/index.js" +- `true`: [node.js __filename](https://nodejs.org/api/globals.html#globals_filename) + +If used inside a expression that is parsed by the Parser, the config option is treated as `true`. + + +### `__resourceQuery` (webpack-specific) + +The resource query of the current module. If the following `require` call were made, then the query string would be available in `file.js`. + +``` javascript +require('file.js?test'); +``` + +__file.js__ + +``` javascript +__resourceQuery === '?test'; +``` + + +### `__webpack_public_path__` (webpack-specific) + +Equals the config options `output.publicPath`. + + +### `__webpack_require__` (webpack-specific) + +The raw require function. This expression isn't parsed by the Parser for dependencies. + + +### `__webpack_chunk_load__` (webpack-specific) + +The internal chunk loading function. Takes two arguments: + +- `chunkId` The id for the chunk to load. +- `callback(require)` A callback function called once the chunk is loaded. + + +### `__webpack_modules__` (webpack-specific) + +Access to the internal object of all modules. + + +### `__webpack_hash__` (webpack-specific) + +This variable is only available with the `HotModuleReplacementPlugin` or the `ExtendedAPIPlugin`. It provides access to the hash of the compilation. + + +### `__non_webpack_require__` (webpack-specific) + +Generates a `require` function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available. + + +### `DEBUG` (webpack-specific) + +Equals the config option `debug`. + + +# Parser + +The `parser` instance, found in the `compiler`, is used to parse each module +being processed by webpack. The `parser` is yet another webpack class that +extends `tapable` and provides a variety of `tapable` hooks that can be used by +plugin authors to customize the parsing process. + +The `parser` is found within [module factories](/api/compiler-hooks/#normalmodulefactory) and therefore takes little +more work to access: + +``` js +compiler.hooks.normalModuleFactory.tap('MyPlugin', factory => { + factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => { + parser.hooks.someHook.tap(/* ... */); + }); +}); +``` + +As with the `compiler`, `tapAsync` and `tapPromise` may also be available +depending on the type of hook. + + +## Hooks + +The following lifecycle hooks are exposed by the `parser` and can be accessed +as such: + + +### evaluateTypeof + +`SyncBailHook` + +Evaluate the type of an identifier. + +Parameters: `expression` + + +### evaluate + +`SyncBailHook` + +Evaluate an expression. + +Parameters: `expression` + + +### evaluateIdentifier + +`SyncBailHook` + +Evaluate an identifier that is a free variable. + +Parameters: `expression` + + +### evaluateDefinedIdentifier + +`SyncBailHook` + +Evaluate an identifier that is a defined variable. + +Parameters: `expression` + + +### evaluateCallExpressionMember + +`SyncBailHook` + +Evaluate a call to a member function of a successfully evaluated expression. + +Parameters: `expression` `param` + + +### statement + +`SyncBailHook` + +General purpose hook that is called when parsing statements in a code fragment. + +Parameters: `statement` + + +### statementIf + +`SyncBailHook` + +... + +Parameters: `statement` + + +### label + +`SyncBailHook` + +... + +Parameters: `statement` + + +### import + +`SyncBailHook` + +... + +Parameters: `statement` `source` + + +### importSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `source` `exportName` `identifierName` + + +### export + +`SyncBailHook` + +... + +Parameters: `statement` + + +### exportImport + +`SyncBailHook` + +... + +Parameters: `statement` `source` + + +### exportDeclaration + +`SyncBailHook` + +... + +Parameters: `statement` `declaration` + + +### exportExpression + +`SyncBailHook` + +... + +Parameters: `statement` `declaration` + + +### exportSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `identifierName` `exportName` `index` + + +### exportImportSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `source` `identifierName` `exportName` `index` + + +### varDeclaration + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationLet + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationConst + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationVar + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### canRename + +`SyncBailHook` + +... + +Parameters: `initExpression` + + +### rename + +`SyncBailHook` + +... + +Parameters: `initExpression` + + +### assigned + +`SyncBailHook` + +... + +Parameters: `expression` + + +### assign + +`SyncBailHook` + +... + +Parameters: `expression` + + +### typeof + +`SyncBailHook` + +... + +Parameters: `expression` + + +### call + +`SyncBailHook` + +... + +Parameters: `expression` + + +### callAnyMember + +`SyncBailHook` + +... + +Parameters: `expression` + + +### new + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expression + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expressionAnyMember + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expressionConditionalOperator + +`SyncBailHook` + +... + +Parameters: `expression` + + +### program + +`SyncBailHook` + +Get access to the abstract syntax tree (AST) of a code fragment + +Parameters: `ast` `comments` diff --git a/src/content/concepts/_concepts_all.md b/src/content/concepts/_concepts_all.md new file mode 100644 index 000000000000..7ea61cfe8aaa --- /dev/null +++ b/src/content/concepts/_concepts_all.md @@ -0,0 +1,1086 @@ + + +# Concepts + +At its core, __webpack__ is a _static module bundler_ for modern JavaScript applications. When webpack processes your application, it internally builds a [dependency graph](/concepts/dependency-graph/) which maps every module your project needs and generates one or more _bundles_. + +T> Learn more about JavaScript modules and webpack modules [here](/concepts/modules). + +Since version 4.0.0, __webpack does not require a configuration file__ to bundle your project, nevertheless it is [incredibly configurable](/configuration) to better fit your needs. + +To get started you only need to understand its __Core Concepts__: + +- [Entry](#entry) +- [Output](#output) +- [Loaders](#loaders) +- [Plugins](#plugins) +- [Mode](#mode) +- [Browser Compatibility](#browser-compatibility) + +This document is intended to give a __high-level__ overview of these concepts, while providing links to detailed concept specific use cases. + +For a better understanding of the ideas behind module bundlers and how they work under the hood consult these resources: + +- [Manually Bundling an Application](https://www.youtube.com/watch?v=UNMkLHzofQI) +- [Live Coding a Simple Module Bundler](https://www.youtube.com/watch?v=Gc9-7PBqOC8) +- [Detailed Explanation of a Simple Module Bundler](https://github.com/ronami/minipack) + + +## Entry + +An __entry point__ indicates which module webpack should use to begin building out its internal [dependency graph](/concepts/dependency-graph/). webpack will figure out which other modules and libraries that entry point depends on (directly and indirectly). + +By default its value is `./src/index.js`, but you can specify a different (or multiple entry points) by configuring the __entry__ property in the [webpack configuration](/configuration). For example: + +__webpack.config.js__ + +``` js +module.exports = { + entry: './path/to/my/entry/file.js' +}; +``` + +T> Learn more in the [entry points](/concepts/entry-points) section. + + +## Output + +The __output__ property tells webpack where to emit the _bundles_ it creates and how to name these files. It defaults to `./dist/main.js` for the main output file and to the `./dist` folder for any other generated file. + +You can configure this part of the process by specifying an `output` field in your configuration: + +__webpack.config.js__ + +```javascript +const path = require('path'); + +module.exports = { + entry: './path/to/my/entry/file.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'my-first-webpack.bundle.js' + } +}; +``` + +In the example above, we use the `output.filename` and the `output.path` properties to tell webpack the name of our bundle and where we want it to be emitted to. In case you're wondering about the path module being imported at the top, it is a core [Node.js module](https://nodejs.org/api/modules.html) that gets used to manipulate file paths. + +T> The `output` property has [many more configurable features](/configuration/output) and if you like to know more about the concepts behind it, you can [read more in the output section](/concepts/output). + + +## Loaders + +Out of the box, webpack only understands JavaScript and JSON files. __Loaders__ allow webpack to process other types of files and convert them into valid [modules](/concepts/modules) that can be consumed by your application and added to the dependency graph. + +W> Note that the ability to `import` any type of module, e.g. `.css` files, is a feature specific to webpack and may not be supported by other bundlers or task runners. We feel this extension of the language is warranted as it allows developers to build a more accurate dependency graph. + +At a high level, __loaders__ have two properties in your webpack configuration: + +1. The `test` property identifies which file or files should be transformed. +2. The `use` property indicates which loader should be used to do the transforming. + +__webpack.config.js__ + +```javascript +const path = require('path'); + +module.exports = { + output: { + filename: 'my-first-webpack.bundle.js' + }, + module: { + rules: [ + { test: /\.txt$/, use: 'raw-loader' } + ] + } +}; +``` + +The configuration above has defined a `rules` property for a single module with two required properties: `test` and `use`. This tells webpack's compiler the following: + +> "Hey webpack compiler, when you come across a path that resolves to a '.txt' file inside of a `require()`/`import` statement, __use__ the `raw-loader` to transform it before you add it to the bundle." + +W> It is important to remember that when defining rules in your webpack config, you are defining them under `module.rules` and not `rules`. For your benefit, webpack will warn you if this is done incorrectly. + +You can check further customization when including loaders in the [loaders section](/concepts/loaders). + + +## Plugins + +While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables. + +T> Check out the [plugin interface](/api/plugins) and how to use it to extend webpacks capabilities. + +In order to use a plugin, you need to `require()` it and add it to the `plugins` array. Most plugins are customizable through options. Since you can use a plugin multiple times in a config for different purposes, you need to create an instance of it by calling it with the `new` operator. + +__webpack.config.js__ + +```javascript +const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm +const webpack = require('webpack'); //to access built-in plugins + +module.exports = { + module: { + rules: [ + { test: /\.txt$/, use: 'raw-loader' } + ] + }, + plugins: [ + new HtmlWebpackPlugin({template: './src/index.html'}) + ] +}; +``` + +In the example above, the `html-webpack-plugin` generates an HTML file for your application by injecting automatically all your generated bundles. + +T> There are many plugins that webpack provides out of the box! Check out the [list of plugins](/plugins). + +Using plugins in your webpack config is straightforward - however, there are many use cases that are worth further exploration. [Learn more about them here](/concepts/plugins). + + +## Mode + +By setting the `mode` parameter to either `development`, `production` or `none`, you can enable webpack's built-in optimizations that correspond to each environment. The default value is `production`. + +```javascript +module.exports = { + mode: 'production' +}; +``` + +Learn more about the [mode configuration here](/concepts/mode) and what optimizations take place on each value. + + +## Browser Compatibility + +webpack supports all browsers that are [ES5-compliant](https://kangax.github.io/compat-table/es5/) (IE8 and below are not supported). webpack needs `Promise` for `import()` and `require.ensure()`. If you want to support older browsers, you will need to [load a polyfill](/guides/shimming/) before using these expressions. + + +# Entry Points + +As mentioned in [Getting Started](/guides/getting-started/#using-a-configuration), there are multiple ways to define the `entry` property in your webpack configuration. We will show you the ways you __can__ configure the `entry` property, in addition to explaining why it may be useful to you. + + +## Single Entry (Shorthand) Syntax + +Usage: `entry: string|Array<string>` + +__webpack.config.js__ + +```javascript +module.exports = { + entry: './path/to/my/entry/file.js' +}; +``` + +The single entry syntax for the `entry` property is a shorthand for: + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + main: './path/to/my/entry/file.js' + } +}; +``` + +T> __What happens when you pass an array to `entry`?__ Passing an array of file paths to the `entry` property creates what is known as a __"multi-main entry"__. This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk". + +This is a great choice when you are looking to quickly setup a webpack configuration for an application or tool with one entry point (i.e., a library). However, there is not much flexibility in extending or scaling your configuration with this syntax. + + +## Object Syntax + +Usage: `entry: {[entryChunkName: string]: string|Array<string>}` + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + app: './src/app.js', + adminApp: './src/adminApp.js' + } +}; +``` + +The object syntax is more verbose. However, this is the most scalable way of defining entry/entries in your application. + +T> __"Scalable webpack configurations"__ are ones that can be reused and combined with other partial configurations. This is a popular technique used to separate concerns by environment, build target and runtime. They are then merged using specialized tools like [webpack-merge](https://github.com/survivejs/webpack-merge). + + +## Scenarios + +Below is a list of entry configurations and their real-world use cases: + +### Separate App and Vendor Entries + +T> In webpack version < 4 it was common to add vendors as separate entrypoint to compile it as separate file (in combination with the `CommonsChunkPlugin`). This is discouraged in webpack 4. Instead the `optimization.splitChunks` option takes care of separating vendors and app modules and creating a separate file. __Do not__ create a entry for vendors or other stuff which is not the starting point of execution. + +### Multi Page Application + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + pageOne: './src/pageOne/index.js', + pageTwo: './src/pageTwo/index.js', + pageThree: './src/pageThree/index.js' + } +}; +``` + +__What does this do?__ We are telling webpack that we would like 3 separate dependency graphs (like the above example). + +__Why?__ In a multi-page application, the server is going to fetch a new HTML document for you. The page reloads this new document and assets are redownloaded. However, this gives us the unique opportunity to do multiple things: + +- Use `optimization.splitChunks` to create bundles of shared application code between each page. Multi-page applications that reuse a lot of code/modules between entry points can greatly benefit from these techniques, as the amount of entry points increase. + +T> As a rule of thumb: for each HTML document use exactly one entry point. + + +# Output + +Configuring the `output` configuration options tells webpack how to write the compiled files to disk. Note that, while there can be multiple `entry` points, only one `output` configuration is specified. + + +## Usage + +The minimum requirements for the `output` property in your webpack config is to set its value to an object including the following thing: + +- A `filename` to use for the output file(s). + +__webpack.config.js__ + +```javascript +module.exports = { + output: { + filename: 'bundle.js', + } +}; +``` + +This configuration would output a single `bundle.js` file into the `dist` directory. + + +## Multiple Entry Points + +If your configuration creates more than a single "chunk" (as with multiple entry points or when using plugins like CommonsChunkPlugin), you should use [substitutions](/configuration/output#output-filename) to ensure that each file has a unique name. + +```javascript +module.exports = { + entry: { + app: './src/app.js', + search: './src/search.js' + }, + output: { + filename: '[name].js', + path: __dirname + '/dist' + } +}; + +// writes to disk: ./dist/app.js, ./dist/search.js +``` + + +## Advanced + +Here's a more complicated example of using a CDN and hashes for assets: + +__config.js__ + +```javascript +module.exports = { + //... + output: { + path: '/home/proj/cdn/assets/[hash]', + publicPath: 'http://cdn.example.com/assets/[hash]/' + } +}; +``` + +In cases where the eventual `publicPath` of output files isn't known at compile time, it can be left blank and set dynamically at runtime via the `__webpack_public_path__` variable in the entry point file: + +```javascript +__webpack_public_path__ = myRuntimePublicPath; + +// rest of your application entry +``` + + +# Loaders + +Loaders are transformations that are applied on the source code of a module. They allow you to pre-process files as you `import` or “load” them. Thus, loaders are kind of like “tasks” in other build tools and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript or inline images as data URLs. Loaders even allow you to do things like `import` CSS files directly from your JavaScript modules! + + +## Example + +For example, you can use loaders to tell webpack to load a CSS file or to convert TypeScript to JavaScript. To do this, you would start by installing the loaders you need: + +``` bash +npm install --save-dev css-loader +npm install --save-dev ts-loader +``` + +And then instruct webpack to use the [`css-loader`](/loaders/css-loader) for every `.css` file and the [`ts-loader`](https://github.com/TypeStrong/ts-loader) for all `.ts` files: + +__webpack.config.js__ + +``` js +module.exports = { + module: { + rules: [ + { test: /\.css$/, use: 'css-loader' }, + { test: /\.ts$/, use: 'ts-loader' } + ] + } +}; +``` + + +## Using Loaders + +There are three ways to use loaders in your application: + +- [Configuration](#configuration) (recommended): Specify them in your __webpack.config.js__ file. +- [Inline](#inline): Specify them explicitly in each `import` statement. +- [CLI](#cli): Specify them within a shell command. + + +### Configuration + +[`module.rules`](/configuration/module/#module-rules) allows you to specify several loaders within your webpack configuration. +This is a concise way to display loaders, and helps to maintain clean code. It also offers you a full overview of each respective loader. + +Loaders are evaluated/executed from right to left. In the example below execution starts with sass-loader, continues with css-loader and finally ends with style-loader. See ["Loader Features"](/concepts/loaders/#loader-features) for more information about loaders order. + +```js-with-links-with-details +module.exports = { + module: { + rules: [ + { + test: /\.css$/, + use: [ + { loader: ['style-loader'](/loaders/style-loader) }, + { + loader: ['css-loader'](/loaders/css-loader), + options: { + modules: true + } + }, + { loader: ['sass-loader'](/loaders/sass-loader) } + ] + } + ] + } +}; +``` + + +### Inline + +It's possible to specify loaders in an `import` statement, or any [equivalent "importing" method](/api/module-methods). Separate loaders from the resource with `!`. Each part is resolved relative to the current directory. + +```js +import Styles from 'style-loader!css-loader?modules!./styles.css'; +``` + +It's possible to override any loaders in the configuration by prefixing the entire rule with `!`. + +Options can be passed with a query parameter, e.g. `?key=value&foo=bar`, or a JSON object, e.g. `?{"key":"value","foo":"bar"}`. + +T> Use `module.rules` whenever possible, as this will reduce boilerplate in your source code and allow you to debug or locate a loader faster if something goes south. + + +### CLI + +You can also use loaders through the CLI: + +```sh +webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader' +``` + +This uses the `jade-loader` for `.jade` files, and the [`style-loader`](/loaders/style-loader) and [`css-loader`](/loaders/css-loader) for `.css` files. + + +## Loader Features + +- Loaders can be chained. Each loader in the chain applies transformations to the processed resource. A chain is executed in reverse order. The first loader passes its result (resource with applied transformations) to the next one, and so forth. Finally, webpack expects JavaScript to be returned by the last loader in the chain. +- Loaders can be synchronous or asynchronous. +- Loaders run in Node.js and can do everything that’s possible there. +- Loaders can be configured with an `options` object (using `query` parameters to set options is still supported but has been deprecated). +- Normal modules can export a loader in addition to the normal `main` via `package.json` with the `loader` field. +- Plugins can give loaders more features. +- Loaders can emit additional arbitrary files. + +Loaders allow more power in the JavaScript ecosystem through preprocessing +functions (loaders). Users now have more flexibility to include fine-grained logic such as compression, packaging, language translations and [more](/loaders). + + +## Resolving Loaders + +Loaders follow the standard [module resolution](/concepts/module-resolution/). In most cases it will be loaded from the [module path](/concepts/module-resolution/#module-paths) (think `npm install`, `node_modules`). + +A loader module is expected to export a function and be written in Node.js compatible JavaScript. They are most commonly managed with npm, but you can also have custom loaders as files within your application. By convention, loaders are usually named `xxx-loader` (e.g. `json-loader`). See ["How to Write a Loader?"](/development/how-to-write-a-loader) for more information. + + +# Mode + +Providing the `mode` configuration option tells webpack to use its built-in optimizations accordingly. + +`string` + +T> Possible values for `mode` are: `none`, `development` or `production`(default). + +## Usage + +Just provide the `mode` option in the config: + +```javascript +module.exports = { + mode: 'production' +}; +``` + + +or pass it as a [CLI](/api/cli/) argument: + +```bash +webpack --mode=production +``` + +The following string values are supported: + +Option | Description +--------------------- | ----------------------- +`development` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `development`. Enables `NamedChunksPlugin` and `NamedModulesPlugin`. +`production` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `production`. Enables `FlagDependencyUsagePlugin`, `FlagIncludedChunksPlugin`, `ModuleConcatenationPlugin`, `NoEmitOnErrorsPlugin`, `OccurrenceOrderPlugin`, `SideEffectsFlagPlugin` and `TerserPlugin`. +`none` | Opts out of any default optimization options + +If not set, webpack sets `production` as the default value for `mode`. The supported values for mode are: + +T> Please remember that setting `NODE_ENV` doesn't automatically set `mode`. + + +### Mode: development + + +```diff +// webpack.development.config.js +module.exports = { ++ mode: 'development' +- devtool: 'eval', +- cache: true, +- performance: { +- hints: false +- }, +- output: { +- pathinfo: true +- }, +- optimization: { +- namedModules: true, +- namedChunks: true, +- nodeEnv: 'development', +- flagIncludedChunks: false, +- occurrenceOrder: false, +- sideEffects: false, +- usedExports: false, +- concatenateModules: false, +- splitChunks: { +- hidePathInfo: false, +- minSize: 10000, +- maxAsyncRequests: Infinity, +- maxInitialRequests: Infinity, +- }, +- noEmitOnErrors: false, +- checkWasmTypes: false, +- minimize: false, +- }, +- plugins: [ +- new webpack.NamedModulesPlugin(), +- new webpack.NamedChunksPlugin(), +- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), +- ] +} +``` + + +### Mode: production + + +```diff +// webpack.production.config.js +module.exports = { ++ mode: 'production', +- performance: { +- hints: 'warning' +- }, +- output: { +- pathinfo: false +- }, +- optimization: { +- namedModules: false, +- namedChunks: false, +- nodeEnv: 'production', +- flagIncludedChunks: true, +- occurrenceOrder: true, +- sideEffects: true, +- usedExports: true, +- concatenateModules: true, +- splitChunks: { +- hidePathInfo: true, +- minSize: 30000, +- maxAsyncRequests: 5, +- maxInitialRequests: 3, +- }, +- noEmitOnErrors: true, +- checkWasmTypes: true, +- minimize: true, +- }, +- plugins: [ +- new TerserPlugin(/* ... */), +- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), +- new webpack.optimize.ModuleConcatenationPlugin(), +- new webpack.NoEmitOnErrorsPlugin() +- ] +} +``` + + +### Mode: none + + +```diff +// webpack.custom.config.js +module.exports = { ++ mode: 'none', +- performance: { +- hints: false +- }, +- optimization: { +- flagIncludedChunks: false, +- occurrenceOrder: false, +- sideEffects: false, +- usedExports: false, +- concatenateModules: false, +- splitChunks: { +- hidePathInfo: false, +- minSize: 10000, +- maxAsyncRequests: Infinity, +- maxInitialRequests: Infinity, +- }, +- noEmitOnErrors: false, +- checkWasmTypes: false, +- minimize: false, +- }, +- plugins: [] +} +``` + +If you want to change the behavior according to the __mode__ variable inside the _webpack.config.js_, you have to export a function instead of an object: + +```javascript +var config = { + entry: './app.js' + //... +}; + +module.exports = (env, argv) => { + + if (argv.mode === 'development') { + config.devtool = 'source-map'; + } + + if (argv.mode === 'production') { + //... + } + + return config; +}; +``` + + +# Plugins + +__Plugins__ are the [backbone](https://github.com/webpack/tapable) of webpack. webpack itself is built on the __same plugin system__ that you use in your webpack configuration! + +They also serve the purpose of doing __anything else__ that a [loader](/concepts/loaders) cannot do. + + +## Anatomy + +A webpack __plugin__ is a JavaScript object that has an [`apply`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) method. This `apply` method is called by the webpack compiler, giving access to the __entire__ compilation lifecycle. + +__ConsoleLogOnBuildWebpackPlugin.js__ + +```javascript +const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; + +class ConsoleLogOnBuildWebpackPlugin { + apply(compiler) { + compiler.hooks.run.tap(pluginName, compilation => { + console.log('The webpack build process is starting!!!'); + }); + } +} +``` + +The first parameter of the tap method of the compiler hook should be a camelized version of the plugin name. It is advisable to use a constant for this so it can be reused in all hooks. + +## Usage + +Since __plugins__ can take arguments/options, you must pass a `new` instance to the `plugins` property in your webpack configuration. + +Depending on how you are using webpack, there are multiple ways to use plugins. + + +### Configuration + +__webpack.config.js__ + +```javascript +const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm +const webpack = require('webpack'); //to access built-in plugins +const path = require('path'); + +module.exports = { + entry: './path/to/my/entry/file.js', + output: { + filename: 'my-first-webpack.bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.(js|jsx)$/, + use: 'babel-loader' + } + ] + }, + plugins: [ + new webpack.ProgressPlugin(), + new HtmlWebpackPlugin({template: './src/index.html'}) + ] +}; +``` + + +### Node API + +When using the Node API, you can also pass plugins via the `plugins` property in the configuration. + +__some-node-script.js__ + +```javascript +const webpack = require('webpack'); //to access webpack runtime +const configuration = require('./webpack.config.js'); + +let compiler = webpack(configuration); + +new webpack.ProgressPlugin().apply(compiler); + +compiler.run(function(err, stats) { + // ... +}); +``` + +T> Did you know: The example seen above is extremely similar to the [webpack runtime itself!](https://github.com/webpack/webpack/blob/e7087ffeda7fa37dfe2ca70b5593c6e899629a2c/bin/webpack.js#L290-L292) There are lots of great usage examples hiding in the [webpack source code](https://github.com/webpack/webpack) that you can apply to your own configurations and scripts! + + +# Configuration + +You may have noticed that few webpack configurations look exactly alike. This is because __webpack's configuration file is a JavaScript file that exports a webpack [configuration](/configuration/).__ This configuration is then processed by webpack based upon its defined properties. + +Because it's a standard Node.js CommonJS module, you __can do the following__: + +- import other files via `require(...)` +- use utilities on npm via `require(...)` +- use JavaScript control flow expressions i. e. the `?:` operator +- use constants or variables for often used values +- write and execute functions to generate a part of the configuration + +Use these features when appropriate. + +While they are technically feasible, __the following practices should be avoided__: + +- Access CLI arguments, when using the webpack CLI (instead write your own CLI, or [use `--env`](/configuration/configuration-types/)) +- Export non-deterministic values (calling webpack twice should result in the same output files) +- Write long configurations (instead split the configuration into multiple files) + +T> The most important part to take away from this document is that there are many different ways to format and style your webpack configuration. The key is to stick with something consistent that you and your team can understand and maintain. + +The examples below describe how webpack's configuration can be both expressive and configurable because _it is code_: + +## Simple Configuration + +__webpack.config.js__ + +```javascript +var path = require('path'); + +module.exports = { + mode: 'development', + entry: './foo.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'foo.bundle.js' + } +}; +``` + +_See_: [Configuration section](/configuration/) for the all supported configuration options + +## Multiple Targets + +Along with exporting a single configuration as an object, [function](/configuration/configuration-types/#exporting-a-function) or [Promise](/configuration/configuration-types/#exporting-a-promise), you can export multiple configurations. + +_See_: [Exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) + +## Using other Configuration Languages + +webpack accepts configuration files written in multiple programming and data languages. + +_See_: [Configuration Languages](/configuration/configuration-languages/) + + +# Modules + +In [modular programming](https://en.wikipedia.org/wiki/Modular_programming), developers break programs up into discrete chunks of functionality called a _module_. + +Each module has a smaller surface area than a full program, making verification, debugging, and testing trivial. +Well-written _modules_ provide solid abstractions and encapsulation boundaries, so that each module has a coherent design and a clear purpose within the overall application. + +Node.js has supported modular programming almost since its inception. +On the web, however, support for _modules_ has been slow to arrive. +Multiple tools exist that support modular JavaScript on the web, with a variety of benefits and limitations. +webpack builds on lessons learned from these systems and applies the concept of _modules_ to any file in your project. + +## What is a webpack Module + +In contrast to [Node.js modules](https://nodejs.org/api/modules.html), webpack _modules_ can express their _dependencies_ in a variety of ways. A few examples are: + +- An [ES2015 `import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) statement +- A [CommonJS](http://www.commonjs.org/specs/modules/1.0/) `require()` statement +- An [AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md) `define` and `require` statement +- An [`@import` statement](https://developer.mozilla.org/en-US/docs/Web/CSS/@import) inside of a css/sass/less file. +- An image url in a stylesheet (`url(...)`) or html (`<img src=...>`) file. + +T> webpack 1 requires a specific loader to convert ES2015 `import`, however this is possible out of the box via webpack 2 + +## Supported Module Types + +webpack supports modules written in a variety of languages and preprocessors, via _loaders_. _Loaders_ describe to webpack __how__ to process non-JavaScript _modules_ and include these _dependencies_ into your _bundles_. +The webpack community has built _loaders_ for a wide variety of popular languages and language processors, including: + +- [CoffeeScript](http://coffeescript.org) +- [TypeScript](https://www.typescriptlang.org) +- [ESNext (Babel)](https://babeljs.io) +- [Sass](http://sass-lang.com) +- [Less](http://lesscss.org) +- [Stylus](http://stylus-lang.com) + +And many others! Overall, webpack provides a powerful and rich API for customization that allows one to use webpack for __any stack__, while staying __non-opinionated__ about your development, testing, and production workflows. + +For a full list, see [__the list of loaders__](/loaders) or [__write your own__](/api/loaders). + + +# Why webpack + +To understand why you should use webpack let's do a recap of how we used JavaScript on the web before bundlers were a thing. + +There are two ways to run JavaScript in a browser. First, include a script for each functionality you want to implement, the issue is that the solution is hard to scale as loading too many scripts causes a network bottleneck. The other alternative is to load a big .js file containing all your project code, but this results in an unmaintainable scripts that causes problems in scope, size, readability, fragility and monolith files. + + +## IIFE's - Immediately invoked function expressions + +IIFEs solve scoping issues for large projects. When script files are wrapped by an IIFE, you can safely concatenate or safely combine files without concern of scope collision. + +This lead to tools like Make, Gulp, Grunt, Broccoli or Brunch. These tools are known as task runners and they are used, among other purposes, to concatenate all your project files together in order to solve some of the issues mentioned before. + +However, anytime you want to change one file you have to rebuild the whole thing. Concatenating makes it trivial to reuse scripts across files and makes build optimizations more difficult to implement. How do you even know what code is being used and which is not? + +If you are only using one function from lodash or one date utility from moment.js you are actually adding the entire library and just squishing it together. How do you treeshake the dependencies on your code? Also, lazy loading chunks of code can be hard to achieve at scale and requires a lot of manual work from the developer. + + +## Birth of JavaScript Modules happened thanks to Node.js + +webpack runs on Node.js, a JavaScript runtime that can be used in computers and servers outside a browser environment. + +When Node.js was released a new era started, and it came with new challenges. Now that JavaScript is not running in a browser, how are Node applications supposed to load new chunks of code? There are no html files and script tags that can be added to it. + +CommonJS came out and introduced `require`, which allows you to load and use a module in the current file. This solves scope issues out of the box and which code is used becomes clear since we need to import each module that we are going to need. + + +## npm + Node.js + modules -- mass distribution + +JavaScript is taking over the world as a language, as a platform and as a way to rapidly develop and create fast running applications. + +But there is no browser support for CommonJS. There are no [live bindings](https://medium.com/webpack/the-state-of-javascript-modules-4636d1774358). There are problems with circular references. Sync module resolution loader is slow. While CommonJS was a great solution for Node.js projects, browsers didn't support modules. That's when bundlers and tools like Browserify, RequireJS and SystemJS were created to solve this limitation making it possible to write CommonJS modules that run in a browser. + + +## ESM - ECMAScript Modules + +The good news for web projects is that modules are becoming an official feature in ECMAScript standard, though browser support is still short and early implementations show that bundling is still faster and recommended today. + + +## Wouldn't it be nice… + +...to have something that will not only let us write modules but also support any module format (at least until we get to ESM) and that can handle resources and assets at the same time? + +This is why webpack exists. It's a tool that not only let's you bundle your JavaScript applications, supporting both ESM and CommonJS, but can be extended to support all different kinds of assets like images, fonts and stylesheets. + +webpack cares a lot about performance and it's always adding and improving features like async chunk loading and prefetching to help you deliver the best possible version of your project to the user, always caring about loading times and performance. + + +# Module Resolution + +A resolver is a library which helps in locating a module by its absolute path. +A module can be required as a dependency from another module as: + +```js +import foo from 'path/to/module'; +// or +require('path/to/module'); +``` + +The dependency module can be from the application code or a third party library. The resolver helps +webpack find the module code that needs to be included in the bundle for every such `require`/`import` statement. +webpack uses [enhanced-resolve](https://github.com/webpack/enhanced-resolve) to resolve file paths while bundling modules. + + +## Resolving rules in webpack + +Using `enhanced-resolve`, webpack can resolve three kinds of file paths: + + +### Absolute paths + +```js +import '/home/me/file'; + +import 'C:\\Users\\me\\file'; +``` + +Since we already have the absolute path to the file, no further resolution is required. + + +### Relative paths + +```js +import '../src/file1'; +import './file2'; +``` + +In this case, the directory of the resource file where the `import` or `require` occurs is taken to be the context directory. The relative path specified in the `import/require` is joined to this context path to produce the absolute path to the module. + + +### Module paths + +```js +import 'module'; +import 'module/lib/file'; +``` + +Modules are searched for inside all directories specified in [`resolve.modules`](/configuration/resolve/#resolve-modules). +You can replace the original module path by an alternate path by creating an alias for it using [`resolve.alias`](/configuration/resolve/#resolve-alias) configuration option. + +Once the path is resolved based on the above rule, the resolver checks to see if the path points to a file or a directory. If the path points to a file: + +- If the path has a file extension, then the file is bundled straightaway. +- Otherwise, the file extension is resolved using the [`resolve.extensions`](/configuration/resolve/#resolve-extensions) option, which tells the resolver which extensions (eg - `.js`, `.jsx`) are acceptable for resolution. + +If the path points to a folder, then the following steps are taken to find the right file with the right extension: + +- If the folder contains a `package.json` file, then fields specified in [`resolve.mainFields`](/configuration/resolve/#resolve-mainfields) configuration option are looked up in order, and the first such field in `package.json` determines the file path. +- If there is no `package.json` or if the main fields do not return a valid path, file names specified in the [`resolve.mainFiles`](/configuration/resolve/#resolve-mainfiles) configuration option are looked for in order, to see if a matching filename exists in the imported/required directory . +- The file extension is then resolved in a similar way using the `resolve.extensions` option. + +webpack provides reasonable [defaults](/configuration/resolve) for these options depending on your build target. + + +## Resolving Loaders + +This follows the same rules as those specified for file resolution. But the [`resolveLoader`](/configuration/resolve/#resolveloader) configuration option can be used to have separate resolution rules for loaders. + + +## Caching + +Every filesystem access is cached, so that multiple parallel or serial requests to the same file occur faster. In [watch mode](/configuration/watch/#watch), only modified files are evicted from the cache. If watch mode is off, then the cache gets purged before every compilation. + + +See [Resolve API](/configuration/resolve) to learn more on the configuration options mentioned above. + + +# Dependency Graph + +Any time one file depends on another, webpack treats this as a _dependency_. This allows webpack to take non-code assets, such as images or web fonts, and also provide them as _dependencies_ for your application. + +When webpack processes your application, it starts from a list of modules defined on the command line or in its config file. +Starting from these [_entry points_](/concepts/entry-points/), webpack recursively builds a _dependency graph_ that includes every module your application needs, then bundles all of those modules into a small number of _bundles_ - often, just one - to be loaded by the browser. + +T> Bundling your application is especially powerful for _HTTP/1.1_ clients, as it minimizes the number of times your app has to wait while the browser starts a new request. For _HTTP/2_, you can also use [Code Splitting](/guides/code-splitting/) to achieve best results. + + +# Targets + +Because JavaScript can be written for both server and browser, webpack offers multiple deployment _targets_ that you can set in your webpack [configuration](/configuration). + +W> The webpack `target` property is not to be confused with the `output.libraryTarget` property. For more information see [our guide](/concepts/output/) on the `output` property. + +## Usage + +To set the `target` property, you simply set the target value in your webpack config: + +__webpack.config.js__ + +```javascript +module.exports = { + target: 'node' +}; +``` + +In the example above, using `node` webpack will compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks and not touch any built in modules like `fs` or `path`). + +Each _target_ has a variety of deployment/environment specific additions, support to fit its needs. See what [targets are available](/configuration/target/). + +?>Further expansion for other popular target values + +## Multiple Targets + +Although webpack does __not__ support multiple strings being passed into the `target` property, you can create an isomorphic library by bundling two separate configurations: + +__webpack.config.js__ + +```javascript +const path = require('path'); +const serverConfig = { + target: 'node', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'lib.node.js' + } + //… +}; + +const clientConfig = { + target: 'web', // <=== can be omitted as default is 'web' + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'lib.js' + } + //… +}; + +module.exports = [ serverConfig, clientConfig ]; +``` + +The example above will create a `lib.js` and `lib.node.js` file in your `dist` folder. + +## Resources + +As seen from the options above there are multiple different deployment _targets_ that you can choose from. Below is a list of examples, and resources that you can refer to. + +- __[compare-webpack-target-bundles](https://github.com/TheLarkInn/compare-webpack-target-bundles)__: A great resource for testing and viewing different webpack _targets_. Also great for bug reporting. +- __[Boilerplate of Electron-React Application](https://github.com/chentsulin/electron-react-boilerplate)__: A good example of a build process for electron's main process and renderer process. + +?> Need to find up to date examples of these webpack targets being used in live code or boilerplates. + + +# The Manifest + +In a typical application or site built with webpack, there are three main types of code: + +1. The source code you, and maybe your team, have written. +2. Any third-party library or "vendor" code your source is dependent on. +3. A webpack runtime and __manifest__ that conducts the interaction of all modules. + +This article will focus on the last of these three parts, the runtime and in particular the manifest. + + +## Runtime + +The runtime, along with the manifest data, is basically all the code webpack needs to connect your modularized application while it's running in the browser. It contains the loading and resolving logic needed to connect your modules as they interact. This includes connecting modules that have already been loaded into the browser as well as logic to lazy-load the ones that haven't. + + +## Manifest + +Once your application hits the browser in the form of `index.html` file, some bundles and a variety of other assets required by your application must be loaded and linked somehow. That `/src` directory you meticulously laid out is now bundled, minified and maybe even split into smaller chunks for lazy-loading by webpack's [`optimization`](/configuration/optimization/). So how does webpack manage the interaction between all of your required modules? This is where the manifest data comes in... + +As the compiler enters, resolves, and maps out your application, it keeps detailed notes on all your modules. This collection of data is called the "Manifest" and it's what the runtime will use to resolve and load modules once they've been bundled and shipped to the browser. No matter which [module syntax](/api/module-methods) you have chosen, those `import` or `require` statements have now become `__webpack_require__` methods that point to module identifiers. Using the data in the manifest, the runtime will be able to find out where to retrieve the modules behind the identifiers. + + +## The Problem + +So now you have a little bit of insight about how webpack works behind the scenes. "But, how does this affect me?", you might ask. The simple answer is that most of the time it doesn't. The runtime will do its thing, utilizing the manifest, and everything will appear to just magically work once your application hits the browser. However, if you decide to improve your projects performance by utilizing browser caching, this process will all of a sudden become an important thing to understand. + +By using content hashes within your bundle file names, you can indicate to the browser when the contents of a file has changed thus invalidating the cache. Once you start doing this though, you'll immediately notice some funny behavior. Certain hashes change even when their contents apparently do not. This is caused by the injection of the runtime and manifest which changes every build. + +See [the manifest section](/guides/output-management/#the-manifest) of our _Output management_ guide to learn how to extract the manifest, and read the guides below to learn more about the intricacies of long term caching. + + +# Hot Module Replacement + +Hot Module Replacement (HMR) exchanges, adds, or removes [modules](/concepts/modules/) while an application is running, without a full reload. This can significantly speed up development in a few ways: + +- Retain application state which is lost during a full reload. +- Save valuable development time by only updating what's changed. +- Modifications made to CSS/JS in the source code results in an instant browser update which is almost comparable to changing styles directly in the browser's dev tools. + + +## How It Works + +Let's go through some different viewpoints to understand exactly how HMR works... + +### In the Application + +The following steps allow modules to be swapped in and out of an application: + +1. The application asks the HMR runtime to check for updates. +2. The runtime asynchronously downloads the updates and notifies the application. +3. The application then asks the runtime to apply the updates. +4. The runtime synchronously applies the updates. + +You can set up HMR so that this process happens automatically, or you can choose to require user interaction for updates to occur. + + +### In the Compiler + +In addition to normal assets, the compiler needs to emit an "update" to allow updating from previous version to the new version. The "update" consists of two parts: + +1. The updated [manifest](/concepts/manifest) (JSON) +2. One or more updated chunks (JavaScript) + +The manifest contains the new compilation hash and a list of all updated chunks. Each of these chunks contains the new code for all updated modules (or a flag indicating that the module was removed). + +The compiler ensures that module IDs and chunk IDs are consistent between these builds. It typically stores these IDs in memory (e.g. with [webpack-dev-server](/configuration/dev-server/)), but it's also possible to store them in a JSON file. + + +### In a Module + +HMR is an opt-in feature that only affects modules containing HMR code. One example would be patching styling through the [`style-loader`](https://github.com/webpack-contrib/style-loader). In order for patching to work, the `style-loader` implements the HMR interface; when it receives an update through HMR, it replaces the old styles with the new ones. + +Similarly, when implementing the HMR interface in a module, you can describe what should happen when the module is updated. However, in most cases, it's not mandatory to write HMR code in every module. If a module has no HMR handlers, the update bubbles up. This means that a single handler can update a complete module tree. If a single module from the tree is updated, the entire set of dependencies is reloaded. + +See the [HMR API page](/api/hot-module-replacement) for details on the `module.hot` interface. + + +### In the Runtime + +Here things get a bit more technical... if you're not interested in the internals, feel free to jump to the [HMR API page](/api/hot-module-replacement) or [HMR guide](/guides/hot-module-replacement). + +For the module system runtime, additional code is emitted to track module `parents` and `children`. On the management side, the runtime supports two methods: `check` and `apply`. + +A `check` makes an HTTP request to the update manifest. If this request fails, there is no update available. If it succeeds, the list of updated chunks is compared to the list of currently loaded chunks. For each loaded chunk, the corresponding update chunk is downloaded. All module updates are stored in the runtime. When all update chunks have been downloaded and are ready to be applied, the runtime switches into the `ready` state. + +The `apply` method flags all updated modules as invalid. For each invalid module, there needs to be an update handler in the module or in its parent(s). Otherwise, the invalid flag bubbles up and invalidates parent(s) as well. Each bubble continues until the app's entry point or a module with an update handler is reached (whichever comes first). If it bubbles up from an entry point, the process fails. + +Afterwards, all invalid modules are disposed (via the dispose handler) and unloaded. The current hash is then updated and all `accept` handlers are called. The runtime switches back to the `idle` state and everything continues as normal. + + +## Get Started + +HMR can be used in development as a LiveReload replacement. [webpack-dev-server](/configuration/dev-server/) supports a `hot` mode in which it tries to update with HMR before trying to reload the whole page. See the [Hot Module Replacement guide](/guides/hot-module-replacement) for details. + +T> As with many other features, webpack's power lies in its customizability. There are _many_ ways of configuring HMR depending on the needs of a particular project. However, for most purposes, `webpack-dev-server` is a good fit and will allow you to get started with HMR quickly. diff --git a/src/content/configuration/_configuration_all.md b/src/content/configuration/_configuration_all.md new file mode 100644 index 000000000000..a1e52dc062a1 --- /dev/null +++ b/src/content/configuration/_configuration_all.md @@ -0,0 +1,5315 @@ + + +# Configuration + +Out of the box, webpack won't require you to use a configuration file. However, it will assume the entry point of your project is `src/index` and will output the result in `dist/main.js` minified and optimized for production. + +Usually your projects will need to extend this functionality, for this you can create a `webpack.config.js` file in the root folder and webpack will automatically use it. + +All the available configuration options are specified below. + +T> New to webpack? Check out our guide to some of webpack's [core concepts](/concepts/) to get started! + +## Options + +Click on the name of each option in the configuration code below to jump to the detailed documentation. Also note that the items with arrows can be expanded to show more examples and, in some cases, more advanced configuration. + +W> Notice that throughout the configuration we use Node's built-in [path module](https://nodejs.org/api/path.html) and prefix it with the [__dirname](https://nodejs.org/docs/latest/api/globals.html#globals_dirname) global. This prevents file path issues between operating systems and allows relative paths to work as expected. See [this section](https://nodejs.org/api/path.html#path_windows_vs_posix) for more info on POSIX vs. Windows paths. + +__webpack.config.js__ + +```js-with-links-with-details +const path = require('path'); + +module.exports = { + <details><summary>[mode](/concepts/mode): "production", // "production" | "development" | "none"</summary> + [mode](/concepts/mode): "production", // enable many optimizations for production builds + [mode](/concepts/mode): "development", // enabled useful tools for development + [mode](/concepts/mode): "none", // no defaults + </details> + // Chosen mode tells webpack to use its built-in optimizations accordingly. + <details><summary>[entry](/configuration/entry-context#entry): "./app/entry", // string | object | array</summary> + [entry](/configuration/entry-context#entry): ["./app/entry1", "./app/entry2"], + [entry](/configuration/entry-context#entry): { + a: "./app/entry-a", + b: ["./app/entry-b1", "./app/entry-b2"] + }, + </details> + // defaults to './src' + // Here the application starts executing + // and webpack starts bundling + [output](/configuration/output): { + // options related to how webpack emits results + [path](/configuration/output#output-path): path.resolve(__dirname, "dist"), // string + // the target directory for all output files + // must be an absolute path (use the Node.js path module) + <details><summary>[filename](/configuration/output#output-filename): "bundle.js", // string</summary> + [filename](/configuration/output#output-filename): "[name].js", // for multiple entry points + [filename](/configuration/output#output-filename): "[chunkhash].js", // for [long term caching](/guides/caching) + </details> + // the filename template for entry chunks + <details><summary>[publicPath](/configuration/output#output-publicpath): "/assets/", // string</summary> + [publicPath](/configuration/output#output-publicpath): "", + [publicPath](/configuration/output#output-publicpath): "https://cdn.example.com/", + </details> + // the url to the output directory resolved relative to the HTML page + [library](/configuration/output#output-library): "MyLibrary", // string, + // the name of the exported library + <details><summary>[libraryTarget](/configuration/output#output-librarytarget): "umd", // universal module definition</summary> + [libraryTarget](/configuration/output#output-librarytarget): "umd2", // universal module definition + [libraryTarget](/configuration/output#output-librarytarget): "commonjs2", // exported with module.exports + [libraryTarget](/configuration/output#output-librarytarget): "commonjs", // exported as properties to exports + [libraryTarget](/configuration/output#output-librarytarget): "amd", // defined with AMD defined method + [libraryTarget](/configuration/output#output-librarytarget): "this", // property set on this + [libraryTarget](/configuration/output#output-librarytarget): "var", // variable defined in root scope + [libraryTarget](/configuration/output#output-librarytarget): "assign", // blind assignment + [libraryTarget](/configuration/output#output-librarytarget): "window", // property set to window object + [libraryTarget](/configuration/output#output-librarytarget): "global", // property set to global object + [libraryTarget](/configuration/output#output-librarytarget): "jsonp", // jsonp wrapper + </details> + // the type of the exported library + <details><summary>/* Advanced output configuration (click to show) */</summary> + [pathinfo](/configuration/output#output-pathinfo): true, // boolean + // include useful path info about modules, exports, requests, etc. into the generated cod + [chunkFilename](/configuration/output#output-chunkfilename): "[id].js", + [chunkFilename](/configuration/output#output-chunkfilename): "[chunkhash].js", // for [long term caching](/guides/caching) + // the filename template for additional chunks + [jsonpFunction](/configuration/output#output-jsonpfunction): "myWebpackJsonp", // string + // name of the JSONP function used to load chunks + [sourceMapFilename](/configuration/output#output-sourcemapfilename): "[file].map", // string + [sourceMapFilename](/configuration/output#output-sourcemapfilename): "sourcemaps/[file].map", // string + // the filename template of the source map location + [devtoolModuleFilenameTemplate](/configuration/output#output-devtoolmodulefilenametemplate): "webpack:///[resource-path]", // string + // the name template for modules in a devtool + [devtoolFallbackModuleFilenameTemplate](/configuration/output#output-devtoolfallbackmodulefilenametemplate): "webpack:///[resource-path]?[hash]", // string + // the name template for modules in a devtool (used for conflicts) + [umdNamedDefine](/configuration/output#output-umdnameddefine): true, // boolean + // use a named AMD module in UMD library + [crossOriginLoading](/configuration/output#output-crossoriginloading): "use-credentials", // enum + [crossOriginLoading](/configuration/output#output-crossoriginloading): "anonymous", + [crossOriginLoading](/configuration/output#output-crossoriginloading): false, + // specifies how cross origin request are issued by the runtime + <details><summary>/* Expert output configuration (on own risk) */</summary> + [devtoolLineToLine](/configuration/output#output-devtoollinetoline): { + test: /\.jsx$/ + }, + // use a simple 1:1 mapped SourceMaps for these modules (faster) + [hotUpdateMainFilename](/configuration/output#output-hotupdatemainfilename): "[hash].hot-update.json", // string + // filename template for HMR manifest + [hotUpdateChunkFilename](/configuration/output#output-hotupdatechunkfilename): "[id].[hash].hot-update.js", // string + // filename template for HMR chunks + [sourcePrefix](/configuration/output#output-sourceprefix): "\t", // string + // prefix module sources in bundle for better readablitity + </details> + </details> + }, + [module](/configuration/module): { + // configuration regarding modules + [rules](/configuration/module#module-rules): [ + // rules for modules (configure loaders, parser options, etc.) + { + [test](/configuration/module#rule-test): /\.jsx?$/, + [include](/configuration/module#rule-include): [ + path.resolve(__dirname, "app") + ], + [exclude](/configuration/module#rule-exclude): [ + path.resolve(__dirname, "app/demo-files") + ], + // these are matching conditions, each accepting a regular expression or string + // test and include have the same behavior, both must be matched + // exclude must not be matched (takes preference over test and include) + // Best practices: + // - Use RegExp only in test and for filename matching + // - Use arrays of absolute paths in include and exclude + // - Try to avoid exclude and prefer include + [issuer](/configuration/module#rule-issuer): { test, include, exclude }, + // conditions for the issuer (the origin of the import) + [enforce](/configuration/module#rule-enforce): "pre", + [enforce](/configuration/module#rule-enforce): "post", + // flags to apply these rules, even if they are overridden (advanced option) + [loader](/configuration/module#rule-loader): "babel-loader", + // the loader which should be applied, it'll be resolved relative to the context + // -loader suffix is no longer optional in webpack2 for clarity reasons + // see [webpack 1 upgrade guide](/migrate/3/#automatic-loader-module-name-extension-removed) + [options](/configuration/module#rule-options-rule-query): { + presets: ["es2015"] + }, + // options for the loader + }, + { + [test](/configuration/module#rule-test): /\.html$/, + [use](/configuration/module#rule-use): [ + // apply multiple loaders and options + "htmllint-loader", + { + loader: "html-loader", + options: { + /* ... */ + } + } + ] + }, + { [oneOf](/configuration/module#rule-oneof): [ /* rules */ ] }, + // only use one of these nested rules + { [rules](/configuration/module#rule-rules): [ /* rules */ ] }, + // use all of these nested rules (combine with conditions to be useful) + { [resource](/configuration/module#rule-resource): { [and](/configuration/module#condition): [ /* conditions */ ] } }, + // matches only if all conditions are matched + { [resource](/configuration/module#rule-resource): { [or](/configuration/module#condition): [ /* conditions */ ] } }, + { [resource](/configuration/module#rule-resource): [ /* conditions */ ] }, + // matches if any condition is matched (default for arrays) + { [resource](/configuration/module#rule-resource): { [not](/configuration/module#condition): /* condition */ } } + // matches if the condition is not matched + ], + <details><summary>/* Advanced module configuration (click to show) */</summary> + [noParse](/configuration/module#module-noparse): [ + /special-library\.js$/ + ], + // do not parse this module + unknownContextRequest: ".", + unknownContextRecursive: true, + unknownContextRegExp: /^\.\/.*$/, + unknownContextCritical: true, + exprContextRequest: ".", + exprContextRegExp: /^\.\/.*$/, + exprContextRecursive: true, + exprContextCritical: true, + wrappedContextRegExp: /.*/, + wrappedContextRecursive: true, + wrappedContextCritical: false, + // specifies default behavior for dynamic requests + </details> + }, + [resolve](/configuration/resolve): { + // options for resolving module requests + // (does not apply to resolving to loaders) + [modules](/configuration/resolve#resolve-modules): [ + "node_modules", + path.resolve(__dirname, "app") + ], + // directories where to look for modules + [extensions](/configuration/resolve#resolve-extensions): [".js", ".json", ".jsx", ".css"], + // extensions that are used + [alias](/configuration/resolve#resolve-alias): { + // a list of module name aliases + "module": "new-module", + // alias "module" -> "new-module" and "module/path/file" -> "new-module/path/file" + "only-module$": "new-module", + // alias "only-module" -> "new-module", but not "only-module/path/file" -> "new-module/path/file" + "module": path.resolve(__dirname, "app/third/module.js"), + // alias "module" -> "./app/third/module.js" and "module/file" results in error + // modules aliases are imported relative to the current context + }, + <details><summary>/* alternative alias syntax (click to show) */</summary> + [alias](/configuration/resolve#resolve-alias): [ + { + name: "module", + // the old request + alias: "new-module", + // the new request + onlyModule: true + // if true only "module" is aliased + // if false "module/inner/path" is also aliased + } + ], + </details> + <details><summary>/* Advanced resolve configuration (click to show) */</summary> + [symlinks](/configuration/resolve#resolve-symlinks): true, + // follow symlinks to new location + [descriptionFiles](/configuration/resolve#resolve-descriptionfiles): ["package.json"], + // files that are read for package description + [mainFields](/configuration/resolve#resolve-mainfields): ["main"], + // properties that are read from description file + // when a folder is requested + [aliasFields](/configuration/resolve#resolve-aliasfields): ["browser"], + // properties that are read from description file + // to alias requests in this package + [enforceExtension](/configuration/resolve#resolve-enforceextension): false, + // if true request must not include an extensions + // if false request may already include an extension + [moduleExtensions](/configuration/resolve#resolveloader-moduleextensions): ["-module"], + [enforceModuleExtension](/configuration/resolve#resolve-enforcemoduleextension): false, + // like extensions/enforceExtension but for module names instead of files + [unsafeCache](/configuration/resolve#resolve-unsafecache): true, + [unsafeCache](/configuration/resolve#resolve-unsafecache): {}, + // enables caching for resolved requests + // this is unsafe as folder structure may change + // but performance improvement is really big + [cachePredicate](/configuration/resolve#resolve-cachepredicate): (path, request) => true, + // predicate function which selects requests for caching + [plugins](/configuration/resolve#resolve-plugins): [ + // ... + ] + // additional plugins applied to the resolver + </details> + }, + [performance](/configuration/performance): { + <details><summary>[hints](/configuration/performance#performance-hints): "warning", // enum </summary> + [hints](/configuration/performance#performance-hints): "error", // emit errors for perf hints + [hints](/configuration/performance#performance-hints): false, // turn off perf hints + </details> + [maxAssetSize](/configuration/performance#performance-maxassetsize): 200000, // int (in bytes), + [maxEntrypointSize](/configuration/performance#performance-maxentrypointsize): 400000, // int (in bytes) + [assetFilter](/configuration/performance#performance-assetfilter): function(assetFilename) { + // Function predicate that provides asset filenames + return assetFilename.endsWith('.css') || assetFilename.endsWith('.js'); + } + }, + <details><summary>[devtool](/configuration/devtool): "source-map", // enum </summary> + [devtool](/configuration/devtool): "inline-source-map", // inlines SourceMap into original file + [devtool](/configuration/devtool): "eval-source-map", // inlines SourceMap per module + [devtool](/configuration/devtool): "hidden-source-map", // SourceMap without reference in original file + [devtool](/configuration/devtool): "cheap-source-map", // cheap-variant of SourceMap without module mappings + [devtool](/configuration/devtool): "cheap-module-source-map", // cheap-variant of SourceMap with module mappings + [devtool](/configuration/devtool): "eval", // no SourceMap, but named modules. Fastest at the expense of detail. + </details> + // enhance debugging by adding meta info for the browser devtools + // source-map most detailed at the expense of build speed. + [context](/configuration/entry-context#context): __dirname, // string (absolute path!) + // the home directory for webpack + // the [entry](/configuration/entry-context) and [module.rules.loader](/configuration/module#rule-loader) option + // is resolved relative to this directory + <details><summary>[target](/configuration/target): "web", // enum</summary> + [target](/configuration/target): "webworker", // WebWorker + [target](/configuration/target): "node", // Node.js via require + [target](/configuration/target): "async-node", // Node.js via fs and vm + [target](/configuration/target): "node-webkit", // nw.js + [target](/configuration/target): "electron-main", // electron, main process + [target](/configuration/target): "electron-renderer", // electron, renderer process + [target](/configuration/target): (compiler) => { /* ... */ }, // custom + </details> + // the environment in which the bundle should run + // changes chunk loading behavior and available modules + <details><summary>[externals](/configuration/externals): ["react", /^@angular\//],</summary> + [externals](/configuration/externals): "react", // string (exact match) + [externals](/configuration/externals): /^[a-z\-]+($|\/)/, // Regex + [externals](/configuration/externals): { // object + angular: "this angular", // this["angular"] + react: { // UMD + commonjs: "react", + commonjs2: "react", + amd: "react", + root: "React" + } + }, + [externals](/configuration/externals): (request) => { /* ... */ return "commonjs " + request } + </details> + // Don't follow/bundle these modules, but request them at runtime from the environment + [serve](https://github.com/webpack-contrib/webpack-serve#options): { //object + port: 1337, + content: './dist', + // ... + }, + // lets you provide options for webpack-serve + <details><summary>[stats](/configuration/stats): "errors-only",</summary> + [stats](/configuration/stats): { //object + assets: true, + colors: true, + errors: true, + errorDetails: true, + hash: true, + // ... + }, + </details> + // lets you precisely control what bundle information gets displayed + [devServer](/configuration/dev-server): { + proxy: { // proxy URLs to backend development server + '/api': 'http://localhost:3000' + }, + contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location + compress: true, // enable gzip compression + historyApiFallback: true, // true for index.html upon 404, object for multiple paths + hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin + https: false, // true for self-signed, object for cert authority + noInfo: true, // only errors & warns on hot reload + // ... + }, + [plugins](plugins): [ + // ... + ], + // list of additional plugins + <details><summary>/* Advanced configuration (click to show) */</summary> + [resolveLoader](/configuration/resolve#resolveloader): { /* same as resolve */ } + // separate resolve options for loaders + [parallelism](other-options#parallelism): 1, // number + // limit the number of parallel processed modules + [profile](other-options#profile): true, // boolean + // capture timing information + [bail](other-options#bail): true, //boolean + // fail out on the first error instead of tolerating it. + [cache](other-options#cache): false, // boolean + // disable/enable caching + [watch](watch#watch): true, // boolean + // enables watching + [watchOptions](watch#watchoptions): { + [aggregateTimeout](watch#watchoptions-aggregatetimeout): 1000, // in ms + // aggregates multiple changes to a single rebuild + [poll](watch#watchoptions-poll): true, + [poll](watch#watchoptions-poll): 500, // interval in ms + // enables polling mode for watching + // must be used on filesystems that doesn't notify on change + // i. e. nfs shares + }, + [node](node): { + // Polyfills and mocks to run Node.js- + // environment code in non-Node environments. + [console](node#node-console): false, // boolean | "mock" + [global](node#node-global): true, // boolean | "mock" + [process](node#node-process): true, // boolean + [__filename](node#node-__filename): "mock", // boolean | "mock" + [__dirname](node#node-__dirname): "mock", // boolean | "mock" + [Buffer](node#node-buffer): true, // boolean | "mock" + [setImmediate](node#node-setimmediate): true // boolean | "mock" | "empty" + }, + [recordsPath](other-options#recordspath): path.resolve(__dirname, "build/records.json"), + [recordsInputPath](other-options#recordsinputpath): path.resolve(__dirname, "build/records.json"), + [recordsOutputPath](other-options#recordsoutputpath): path.resolve(__dirname, "build/records.json"), + // TODO + </details> +} +``` + +## Use custom configuration file + +If for some reason you want to use custom configuration file depending on certain situations you can change this via command line by using the `--config` flag. + +__package.json__ + +```json +"scripts": { + "build": "webpack --config prod.config.js" +} +``` + +## Configuration file generators + +Want to rapidly generate webpack configuration file for your project requirements with few clicks away? + +[Generate Custom Webpack Configuration](https://generatewebpackconfig.netlify.com/) is an interactive portal you can play around by selecting custom webpack configuration options tailored for your frontend project. It automatically generates a minimal webpack configuration based on your selection of loaders/plugins, etc. + +[Visual tool for creating webpack configs](https://webpack.jakoblind.no/) is an online configuration tool for creating webpack configuration file where you can select any combination of features you need. It also generates a full example project based on your webpack configs. + + +# Configuration Languages + +webpack accepts configuration files written in multiple programming and data languages. The list of supported file extensions can be found at the [node-interpret](https://github.com/js-cli/js-interpret) package. Using [node-interpret](https://github.com/js-cli/js-interpret), webpack can handle many different types of configuration files. + + +## TypeScript + +To write the webpack configuration in [TypeScript](http://www.typescriptlang.org/), you would first install the necessary dependencies, i.e., TypeScript and the relevant type definitions from the [DefinitelyTyped](https://definitelytyped.org/) project: + +``` bash +npm install --save-dev typescript ts-node @types/node @types/webpack +# and, if using webpack-dev-server +npm install --save-dev @types/webpack-dev-server +``` + +and then proceed to write your configuration: + +__webpack.config.ts__ + +```typescript +import path from 'path'; +import webpack from 'webpack'; + +const config: webpack.Configuration = { + mode: 'production', + entry: './foo.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'foo.bundle.js' + } +}; + +export default config; +``` + +Above sample assumes version >= 2.7 or newer of TypeScript is used with the new `esModuleInterop` and `allowSyntheticDefaultImports` compiler options in your `tsconfig.json` file. + +Note that you'll also need to check your `tsconfig.json` file. If the module in `compilerOptions` in `tsconfig.json` is `commonjs`, the setting is complete, else webpack will fail with an error. This occurs because `ts-node` does not support any module syntax other than `commonjs`. + +There are two solutions to this issue: + +- Modify `tsconfig.json`. +- Install `tsconfig-paths`. + +The __first option__ is to open your `tsconfig.json` file and look for `compilerOptions`. Set `target` to `"ES5"` and `module` to `"CommonJS"` (or completely remove the `module` option). + +The __second option__ is to install the `tsconfig-paths` package: + +``` bash +npm install --save-dev tsconfig-paths +``` + +And create a separate TypeScript configuration specifically for your webpack configs: + +__tsconfig-for-webpack-config.json__ + +``` json +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "esModuleInterop": true + } +} +``` + +T> `ts-node` can resolve a `tsconfig.json` file using the environment variable provided by `tsconfig-path`. + +Then set the environment variable `process.env.TS_NODE_PROJECT` provided by `tsconfig-path` like so: + +__package.json__ + +```json +{ + "scripts": { + "build": "TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack" + } +} +``` + + +## CoffeeScript + +Similarly, to use [CoffeeScript](http://coffeescript.org/), you would first install the necessary dependencies: + +``` bash +npm install --save-dev coffee-script +``` + +and then proceed to write your configuration: + +__webpack.config.coffee__ + +<!-- eslint-skip --> + +```js +HtmlWebpackPlugin = require('html-webpack-plugin') +webpack = require('webpack') +path = require('path') + +config = + mode: 'production' + entry: './path/to/my/entry/file.js' + output: + path: path.resolve(__dirname, 'dist') + filename: 'my-first-webpack.bundle.js' + module: rules: [ { + test: /\.(js|jsx)$/ + use: 'babel-loader' + } ] + plugins: [ + new HtmlWebpackPlugin(template: './src/index.html') + ] + +module.exports = config +``` + + +## Babel and JSX + +In the example below JSX (React JavaScript Markup) and Babel are used to create a JSON Configuration that webpack can understand. + +> Courtesy of [Jason Miller](https://twitter.com/_developit/status/769583291666169862) + +First install the necessary dependencies: + +``` bash +npm install --save-dev babel-register jsxobj babel-preset-es2015 +``` + +__.babelrc__ + +``` json +{ + "presets": [ "es2015" ] +} +``` + +__webpack.config.babel.js__ + +``` js +import jsxobj from 'jsxobj'; + +// example of an imported plugin +const CustomPlugin = config => ({ + ...config, + name: 'custom-plugin' +}); + +export default ( + <webpack target="web" watch mode="production"> + <entry path="src/index.js" /> + <resolve> + <alias {...{ + react: 'preact-compat', + 'react-dom': 'preact-compat' + }} /> + </resolve> + <plugins> + <CustomPlugin foo="bar" /> + </plugins> + </webpack> +); +``` + +W> If you are using Babel elsewhere and have `modules` set to `false`, you will have to either maintain two separate `.babelrc` files or use `const jsxobj = require('jsxobj');` and `module.exports` instead of the new `import` and `export` syntax. This is because while Node does support many new ES6 features, they don't yet support ES6 module syntax. + + +# Configuration Types + +Besides exporting a single config object, there are a few more ways that cover other needs as well. + + +## Exporting a Function + +Eventually you will find the need to disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production). You have (at least) two options: + +One option is to export a function from your webpack config instead of exporting an object. The function will be invoked with two arguments: + +- An environment as the first parameter. See the [environment options CLI documentation](/api/cli#environment-options) for syntax examples. +- An options map (`argv`) as the second parameter. This describes the options passed to webpack, with keys such as [`output-filename`](/api/cli/#output-options) and [`optimize-minimize`](/api/cli/#optimize-options). + +```diff +-module.exports = { ++module.exports = function(env, argv) { ++ return { ++ mode: env.production ? 'production' : 'development', ++ devtool: env.production ? 'source-maps' : 'eval', + plugins: [ + new TerserPlugin({ + terserOptions: { ++ compress: argv['optimize-minimize'] // only if -p or --optimize-minimize were passed + } + }) + ] ++ }; +}; +``` + + +## Exporting a Promise + +webpack will run the function exported by the configuration file and wait for a Promise to be returned. Handy when you need to asynchronously load configuration variables. + +```js +module.exports = () => { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve({ + entry: './app.js', + /* ... */ + }); + }, 5000); + }); +}; +``` + + +## Exporting multiple configurations + +Instead of exporting a single configuration object/function, you may export multiple configurations (multiple functions are supported since webpack 3.1.0). When running webpack, all configurations are built. For instance, this is useful for [bundling a library](/guides/author-libraries) for multiple [targets](/configuration/output#output-librarytarget) such as AMD and CommonJS: + +```js +module.exports = [{ + output: { + filename: './dist-amd.js', + libraryTarget: 'amd' + }, + name: 'amd', + entry: './app.js', + mode: 'production', +}, { + output: { + filename: './dist-commonjs.js', + libraryTarget: 'commonjs' + }, + name: 'commonjs', + entry: './app.js', + mode: 'production', +}]; +``` + +T> If you pass a name to [`--config-name`](/api/cli/#config-options) flag, webpack will only build that specific configuration. + + +# Entry and Context + +The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. + + +## `context` + +`string` + +The base directory, an __absolute path__, for resolving entry points and loaders from configuration. + +``` js +module.exports = { + //... + context: path.resolve(__dirname, 'app') +}; +``` + +By default the current directory is used, but it's recommended to pass a value in your configuration. This makes your configuration independent from CWD (current working directory). + +--- + + +## `entry` + +`string | [string] | object { <key>: string | [string] } | (function: () => string | [string] | object { <key>: string | [string] })` + +The point or points to enter the application. At this point the application starts executing. If an array is passed all items will be executed. + +A dynamically loaded module is __not__ an entry point. + +Simple rule: one entry point per HTML page. SPA: one entry point, MPA: multiple entry points. + +```js +module.exports = { + //... + entry: { + home: './home.js', + about: './about.js', + contact: './contact.js' + } +}; +``` + + +### Naming + +If a string or array of strings is passed, the chunk is named `main`. If an object is passed, each key is the name of a chunk, and the value describes the entry point for the chunk. + + +### Dynamic entry + +If a function is passed then it will be invoked on every [make](/api/compiler-hooks/#make) event. + +> Note that the make event triggers when webpack starts and for every invalidation when [watching for file changes](/configuration/watch/). + +```js +module.exports = { + //... + entry: () => './demo' +}; +``` + +or + +```js +module.exports = { + //... + entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])) +}; +``` + +For example: you can use dynamic entries to get the actual entries from an external source (remote server, file system content or database): + +__webpack.config.js__ + +``` js +module.exports = { + entry() { + return fetchPathsFromSomeExternalSource(); // returns a promise that will be resolved with something like ['src/main-layout.js', 'src/admin-layout.js'] + } +}; +``` + +When combining with the [`output.library`](/configuration/output#output-library) option: If an array is passed only the last item is exported. + + +# Output + +The top-level `output` key contains set of options instructing webpack on how and where it should output your bundles, assets and anything else you bundle or load with webpack. + + +## `output.auxiliaryComment` + +`string` `object` + +When used in tandem with [`output.library`](#output-library) and [`output.libraryTarget`](#output-librarytarget), this option allows users to insert comments within the export wrapper. To insert the same comment for each `libraryTarget` type, set `auxiliaryComment` to a string: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + library: 'someLibName', + libraryTarget: 'umd', + filename: 'someLibName.js', + auxiliaryComment: 'Test Comment' + } +}; +``` + +which will yield the following: + +__webpack.config.js__ + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + // Test Comment + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require('lodash')); + // Test Comment + else if(typeof define === 'function' && define.amd) + define(['lodash'], factory); + // Test Comment + else if(typeof exports === 'object') + exports['someLibName'] = factory(require('lodash')); + // Test Comment + else + root['someLibName'] = factory(root['_']); +})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { + // ... +}); +``` + +For fine-grained control over each `libraryTarget` comment, pass an object: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + //... + auxiliaryComment: { + root: 'Root Comment', + commonjs: 'CommonJS Comment', + commonjs2: 'CommonJS2 Comment', + amd: 'AMD Comment' + } + } +}; +``` + + +## `output.chunkFilename` + +`string` + +This option determines the name of non-entry chunk files. See [`output.filename`](#output-filename) option for details on the possible values. + +Note that these filenames need to be generated at runtime to send the requests for chunks. Because of this, placeholders like `[name]` and `[chunkhash]` need to add a mapping from chunk id to placeholder value to the output bundle with the webpack runtime. This increases the size and may invalidate the bundle when placeholder value for any chunk changes. + +By default `[id].js` is used or a value inferred from [`output.filename`](#output-filename) (`[name]` is replaced with `[id]` or `[id].` is prepended). + + +## `output.chunkLoadTimeout` + +`integer` + +Number of milliseconds before chunk request expires, defaults to 120 000. This option is supported since webpack 2.6.0. + + +## `output.crossOriginLoading` + +`boolean` `string` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks, by adding script tags. + +Enable [cross-origin](https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-crossorigin) loading of chunks. The following values are accepted... + +`crossOriginLoading: false` - Disable cross-origin loading (default) + +`crossOriginLoading: 'anonymous'` - Enable cross-origin loading __without credentials__ + +`crossOriginLoading: 'use-credentials'` - Enable cross-origin loading __with credentials__ + + +## `output.jsonpScriptType` + +`string` + +Allows customization of the `script` type webpack injects `script` tags into the DOM to download async chunks. The following options are available: + +- `'text/javascript'` (default) +- `'module'`: Use with ES6 ready code. + + +## `output.devtoolFallbackModuleFilenameTemplate` + +`string | function(info)` + +A fallback used when the template string or function above yields duplicates. + +See [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). + + +## `output.devtoolLineToLine` + +`boolean | object` + +> Avoid using this option as it is __deprecated__ and will soon be removed. + +Enables line to line mapping for all or some modules. This produces a simple source map where each line of the generated source is mapped to the same line of the original source. This is a performance optimization and should only be used if all input lines match generated lines. + +Pass a boolean to enable or disable this feature for all modules (defaults to `false`). An object with `test`, `include`, `exclude` is also allowed. For example, to enable this feature for all javascript files within a certain directory: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + devtoolLineToLine: { test: /\.js$/, include: 'src/utilities' } + } +}; +``` + + +## `output.devtoolModuleFilenameTemplate` + +`string | function(info)` + +This option is only used when [`devtool`](/configuration/devtool) uses an options which requires module names. + +Customize the names used in each source map's `sources` array. This can be done by passing a template string or function. For example, when using `devtool: 'eval'`, this is the default: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + devtoolModuleFilenameTemplate: 'webpack://[namespace]/[resource-path]?[loaders]' + } +}; +``` + +The following substitutions are available in template strings (via webpack's internal [`ModuleFilenameHelpers`](https://github.com/webpack/webpack/blob/master/lib/ModuleFilenameHelpers.js)): + +| Template | Description | +| ------------------------ | ----------- | +| [absolute-resource-path] | The absolute filename | +| [all-loaders] | Automatic and explicit loaders and params up to the name of the first loader | +| [hash] | The hash of the module identifier | +| [id] | The module identifier | +| [loaders] | Explicit loaders and params up to the name of the first loader | +| [resource] | The path used to resolve the file and any query params used on the first loader | +| [resource-path] | The path used to resolve the file without any query params | +| [namespace] | The modules namespace. This is usually the library name when building as a library, empty otherwise | + +When using a function, the same options are available camel-cased via the `info` parameter: + +```javascript +module.exports = { + //... + output: { + devtoolModuleFilenameTemplate: info => { + return `webpack:///${info.resourcePath}?${info.loaders}`; + } + } +}; +``` + +If multiple modules would result in the same name, [`output.devtoolFallbackModuleFilenameTemplate`](#output-devtoolfallbackmodulefilenametemplate) is used instead for these modules. + + +## `output.devtoolNamespace` + +`string` + +This option determines the modules namespace used with the [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). When not specified, it will default to the value of: [`output.library`](#output-library). It's used to prevent source file path collisions in source maps when loading multiple libraries built with webpack. + +For example, if you have 2 libraries, with namespaces `library1` and `library2`, which both have a file `./src/index.js` (with potentially different contents), they will expose these files as `webpack://library1/./src/index.js` and `webpack://library2/./src/index.js`. + + +## `output.filename` + +`string` `function` + +This option determines the name of each output bundle. The bundle is written to the directory specified by the [`output.path`](#output-path) option. + +For a single [`entry`](/configuration/entry-context#entry) point, this can be a static name. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: 'bundle.js' + } +}; +``` + +However, when creating multiple bundles via more than one entry point, code splitting, or various plugins, you should use one of the following substitutions to give each bundle a unique name... + +Using entry name: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[name].bundle.js' + } +}; +``` + +Using internal chunk id: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[id].bundle.js' + } +}; +``` + +Using the unique hash generated for every build: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[name].[hash].bundle.js' + } +}; +``` + +Using hashes based on each chunks' content: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[chunkhash].bundle.js' + } +}; +``` + +Using hashes generated for extracted content: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[contenthash].bundle.css' + } +}; +``` + +Using function to return the filename: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: (chunkData) => { + return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js'; + }, + } +}; +``` + +Make sure to read the [Caching guide](/guides/caching) for details. There are more steps involved than just setting this option. + +Note this option is called filename but you are still allowed to use something like `'js/[name]/bundle.js'` to create a folder structure. + +Note this option does not affect output files for on-demand-loaded chunks. For these files the [`output.chunkFilename`](#output-chunkfilename) option is used. Files created by loaders also aren't affected. In this case you would have to try the specific loader's available options. + +The following substitutions are available in template strings (via webpack's internal [`TemplatedPathPlugin`](https://github.com/webpack/webpack/blob/master/lib/TemplatedPathPlugin.js)): + +| Template | Description | +| ----------- | ----------------------------------------------------------------------------------- | +| [hash] | The hash of the module identifier | +| [chunkhash] | The hash of the chunk content | +| [name] | The module name | +| [id] | The module identifier | +| [query] | The module query, i.e., the string following `?` in the filename | +| [function] | The function, which can return filename [string] | + +The lengths of `[hash]` and `[chunkhash]` can be specified using `[hash:16]` (defaults to 20). Alternatively, specify [`output.hashDigestLength`](#output-hashdigestlength) to configure the length globally. + +If using a function for this option, the function will be passed an object containing the substitutions in the table above. + +T> When using the [`ExtractTextWebpackPlugin`](/plugins/extract-text-webpack-plugin), use `[contenthash]` to obtain a hash of the extracted file (neither `[hash]` nor `[chunkhash]` work). + + +## `output.hashDigest` + +The encoding to use when generating the hash, defaults to `'hex'`. All encodings from Node.JS' [`hash.digest`](https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding) are supported. Using `'base64'` for filenames might be problematic since it has the character `/` in its alphabet. Likewise `'latin1'` could contain any character. + + +## `output.hashDigestLength` + +The prefix length of the hash digest to use, defaults to `20`. + + +## `output.hashFunction` + +`string|function` + +The hashing algorithm to use, defaults to `'md4'`. All functions from Node.JS' [`crypto.createHash`](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options) are supported. Since `4.0.0-alpha2`, the `hashFunction` can now be a constructor to a custom hash function. You can provide a non-crypto hash function for performance reasons. + +```javascript +module.exports = { + //... + output: { + hashFunction: require('metrohash').MetroHash64 + } +}; +``` + +Make sure that the hashing function will have `update` and `digest` methods available. + +## `output.hashSalt` + +An optional salt to update the hash via Node.JS' [`hash.update`](https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding). + + +## `output.hotUpdateChunkFilename` + +`string` `function` + +Customize the filenames of hot update chunks. See [`output.filename`](#output-filename) option for details on the possible values. + +The only placeholders allowed here are `[id]` and `[hash]`, the default being: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + hotUpdateChunkFilename: '[id].[hash].hot-update.js' + } +}; +``` + +Here is no need to change it. + + +## `output.hotUpdateFunction` + +`function` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading hot updates. + +A JSONP function used to asynchronously load hot-update chunks. + +For details see [`output.jsonpFunction`](#output-jsonpfunction). + + +## `output.hotUpdateMainFilename` + +`string` `function` + +Customize the main hot update filename. See [`output.filename`](#output-filename) option for details on the possible values. + +`[hash]` is the only available placeholder, the default being: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + hotUpdateMainFilename: '[hash].hot-update.json' + } +}; +``` + +Here is no need to change it. + + +## `output.jsonpFunction` + +`string` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks. + +A JSONP function name used to asynchronously load chunks or join multiple initial chunks (SplitChunksPlugin, AggressiveSplittingPlugin). + +This needs to be changed if multiple webpack runtimes (from different compilation) are used on the same webpage. + +If using the [`output.library`](#output-library) option, the library name is automatically appended. + + +## `output.library` + +`string` or `object` (since webpack 3.1.0; for `libraryTarget: 'umd'`) + +How the value of the `output.library` is used depends on the value of the [`output.libraryTarget`](#output-librarytarget) option; please refer to that section for the complete details. Note that the default option for `output.libraryTarget` is `var`, so if the following configuration option is used: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary' + } +}; +``` + +The variable `MyLibrary` will be bound with the return value of your entry file, if the resulting output is included as a script tag in an HTML page. + +W> Note that if an `array` is provided as an `entry` point, only the last module in the array will be exposed. If an `object` is provided, it can be exposed using an `array` syntax (see [this example](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) for details). + +T> Read the [authoring libraries guide](/guides/author-libraries) guide for more information on `output.library` as well as `output.libraryTarget`. + + +## `output.libraryExport` + +`string | string[]` + +Configure which module or modules will be exposed via the `libraryTarget`. It is `undefined` by default, same behaviour will be applied if you set `libraryTarget` to an empty string e.g. `''` it will export the whole (namespace) object. The examples below demonstrate the effect of this config when using `libraryTarget: 'var'`. + +The following configurations are supported: + +`libraryExport: 'default'` - The __default export of your entry point__ will be assigned to the library target: + +```javascript +// if your entry has a default export of `MyDefaultModule` +var MyDefaultModule = _entry_return_.default; +``` + +`libraryExport: 'MyModule'` - The __specified module__ will be assigned to the library target: + +```javascript +var MyModule = _entry_return_.MyModule; +``` + +`libraryExport: ['MyModule', 'MySubModule']` - The array is interpreted as a __path to a module__ to be assigned to the library target: + +```javascript +var MySubModule = _entry_return_.MyModule.MySubModule; +``` + +With the `libraryExport` configurations specified above, the resulting libraries could be utilized as such: + +```javascript +MyDefaultModule.doSomething(); +MyModule.doSomething(); +MySubModule.doSomething(); +``` + + +## `output.libraryTarget` + +`string: 'var'` + +Configure how the library will be exposed. Any one of the following options can be used. Please note that this option works in conjunction with the value assigned to [`output.library`](#output-library). For the following examples, it is assumed that this value is configured as `MyLibrary`. + +T> Note that `_entry_return_` in the example code below is the value returned by the entry point. In the bundle itself, it is the output of the function that is generated by webpack from the entry point. + +### Expose a Variable + +These options assign the return value of the entry point (e.g. whatever the entry point exported) to the name provided by `output.library` at whatever scope the bundle was included at. + +`libraryTarget: 'var'` - (default) When your library is loaded, the __return value of your entry point__ will be assigned to a variable: + +```javascript +var MyLibrary = _entry_return_; + +// In a separate script... +MyLibrary.doSomething(); +``` + +W> When using this option, an empty `output.library` will result in no assignment. + + +`libraryTarget: 'assign'` - This will generate an implied global which has the potential to reassign an existing value (use with caution). + +```javascript +MyLibrary = _entry_return_; +``` + +Be aware that if `MyLibrary` isn't defined earlier your library will be set in global scope. + +W> When using this option, an empty `output.library` will result in a broken output bundle. + + +### Expose Via Object Assignment + +These options assign the return value of the entry point (e.g. whatever the entry point exported) to a specific object under the name defined by `output.library`. + +If `output.library` is not assigned a non-empty string, the default behavior is that all properties returned by the entry point will be assigned to the object as defined for the particular `output.libraryTarget`, via the following code fragment: + +```javascript +(function(e, a) { for(var i in a) { e[i] = a[i]; } }(output.libraryTarget, _entry_return_)); +``` + +W> Note that not setting a `output.library` will cause all properties returned by the entry point to be assigned to the given object; there are no checks against existing property names. + +`libraryTarget: "this"` - The __return value of your entry point__ will be assigned to this under the property named by `output.library`. The meaning of `this` is up to you: + +```javascript +this['MyLibrary'] = _entry_return_; + +// In a separate script... +this.MyLibrary.doSomething(); +MyLibrary.doSomething(); // if this is window +``` + +`libraryTarget: 'window'` - The __return value of your entry point__ will be assigned to the `window` object using the `output.library` value. + +```javascript +window['MyLibrary'] = _entry_return_; + +window.MyLibrary.doSomething(); +``` + + +`libraryTarget: 'global'` - The __return value of your entry point__ will be assigned to the `global` object using the `output.library` value. + +```javascript +global['MyLibrary'] = _entry_return_; + +global.MyLibrary.doSomething(); +``` + + +`libraryTarget: 'commonjs'` - The __return value of your entry point__ will be assigned to the `exports` object using the `output.library` value. As the name implies, this is used in CommonJS environments. + +```javascript +exports['MyLibrary'] = _entry_return_; + +require('MyLibrary').doSomething(); +``` + +### Module Definition Systems + +These options will result in a bundle that comes with a more complete header to ensure compatibility with various module systems. The `output.library` option will take on a different meaning under the following `output.libraryTarget` options. + + +`libraryTarget: 'commonjs2'` - The __return value of your entry point__ will be assigned to the `module.exports`. As the name implies, this is used in CommonJS environments: + +```javascript +module.exports = _entry_return_; + +require('MyLibrary').doSomething(); +``` + +Note that `output.library` is omitted, thus it is not required for this particular `output.libraryTarget`. + +T> Wondering the difference between CommonJS and CommonJS2 is? While they are similar, there are some subtle differences between them that are not usually relevant in the context of webpack. (For further details, please [read this issue](https://github.com/webpack/webpack/issues/1114).) + + +`libraryTarget: 'amd'` - This will expose your library as an AMD module. + +AMD modules require that the entry chunk (e.g. the first script loaded by the `<script>` tag) be defined with specific properties, such as `define` and `require` which is typically provided by RequireJS or any compatible loaders (such as almond). Otherwise, loading the resulting AMD bundle directly will result in an error like `define is not defined`. + +So, with the following configuration... + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary', + libraryTarget: 'amd' + } +}; +``` + +The generated output will be defined with the name "MyLibrary", i.e. + +```javascript +define('MyLibrary', [], function() { + return _entry_return_; +}); +``` + +The bundle can be included as part of a script tag, and the bundle can be invoked like so: + +```javascript +require(['MyLibrary'], function(MyLibrary) { + // Do something with the library... +}); +``` + +If `output.library` is undefined, the following is generated instead. + +```javascript +define([], function() { + return _entry_return_; +}); +``` + +This bundle will not work as expected, or not work at all (in the case of the almond loader) if loaded directly with a `<script>` tag. It will only work through a RequireJS compatible asynchronous module loader through the actual path to that file, so in this case, the `output.path` and `output.filename` may become important for this particular setup if these are exposed directly on the server. + + +`libraryTarget: 'amd-require'` - This packages your output with an immediately-executed AMD `require(dependencies, factory)` wrapper. + +The `'amd-require'` target allows for the use of AMD dependencies without needing a separate later invocation. As with the `'amd'` target, this depends on the appropriate [`require` function](https://github.com/amdjs/amdjs-api/blob/master/require.md) being available in the environment in which the webpack output is loaded. + +With this target, the library name is ignored. + + +`libraryTarget: 'umd'` - This exposes your library under all the module definitions, allowing it to work with CommonJS, AMD and as global variable. Take a look at the [UMD Repository](https://github.com/umdjs/umd) to learn more. + +In this case, you need the `library` property to name your module: + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary', + libraryTarget: 'umd' + } +}; +``` + +And finally the output is: + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports['MyLibrary'] = factory(); + else + root['MyLibrary'] = factory(); +})(typeof self !== 'undefined' ? self : this, function() { + return _entry_return_; +}); +``` + +Note that omitting `library` will result in the assignment of all properties returned by the entry point be assigned directly to the root object, as documented under the [object assignment section](#expose-via-object-assignment). Example: + +```javascript +module.exports = { + //... + output: { + libraryTarget: 'umd' + } +}; +``` + +The output will be: + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else { + var a = factory(); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(typeof self !== 'undefined' ? self : this, function() { + return _entry_return_; +}); +``` + +Since webpack 3.1.0, you may specify an object for `library` for differing names per targets: + +```javascript +module.exports = { + //... + output: { + library: { + root: 'MyLibrary', + amd: 'my-library', + commonjs: 'my-common-library' + }, + libraryTarget: 'umd' + } +}; +``` + +Module proof library. + + +### Other Targets + +`libraryTarget: 'jsonp'` - This will wrap the return value of your entry point into a jsonp wrapper. + +``` javascript +MyLibrary(_entry_return_); +``` + +The dependencies for your library will be defined by the [`externals`](/configuration/externals/) config. + + +## `output.path` + +`string` + +The output directory as an __absolute__ path. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + path: path.resolve(__dirname, 'dist/assets') + } +}; +``` + +Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. + + +## `output.pathinfo` + +`boolean` + +Tells webpack to include comments in bundles with information about the contained modules. This option defaults to `true` in `development` and `false` in `production` [mode](/concepts/mode/) respectively. + +W> While the data this comments can provide is very useful during development when reading the generated code, it __should not__ be used in production. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + pathinfo: true + } +}; +``` + +Note it also adds some info about tree shaking to the generated bundle. + + +## `output.publicPath` + +`string: ''` `function` + +This is an important option when using on-demand-loading or loading external resources like images, files, etc. If an incorrect value is specified you'll receive 404 errors while loading these resources. + +This option specifies the __public URL__ of the output directory when referenced in a browser. A relative URL is resolved relative to the HTML page (or `<base>` tag). Server-relative URLs, protocol-relative URLs or absolute URLs are also possible and sometimes required, i. e. when hosting assets on a CDN. + +The value of the option is prefixed to every URL created by the runtime or loaders. Because of this __the value of this option ends with `/`__ in most cases. + +Simple rule: The URL of your [`output.path`](#output-path) from the view of the HTML page. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + path: path.resolve(__dirname, 'public/assets'), + publicPath: 'https://cdn.example.com/assets/' + } +}; +``` + +For this configuration: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + publicPath: '/assets/', + chunkFilename: '[id].chunk.js' + } +}; +``` + +A request to a chunk will look like `/assets/4.chunk.js`. + +A loader outputting HTML might emit something like this: + +```html +<link href="/assets/spinner.gif" /> +``` + +or when loading an image in CSS: + +```css +background-image: url(/assets/spinner.gif); +``` + +The webpack-dev-server also takes a hint from `publicPath`, using it to determine where to serve the output files from. + +Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. + +Examples: + +```javascript +module.exports = { + //... + output: { + // One of the below + publicPath: 'https://cdn.example.com/assets/', // CDN (always HTTPS) + publicPath: '//cdn.example.com/assets/', // CDN (same protocol) + publicPath: '/assets/', // server-relative + publicPath: 'assets/', // relative to HTML page + publicPath: '../assets/', // relative to HTML page + publicPath: '', // relative to HTML page (same directory) + } +}; +``` + +In cases where the `publicPath` of output files can't be known at compile time, it can be left blank and set dynamically at runtime in the entry file using the [free variable](https://stackoverflow.com/questions/12934929/what-are-free-variables) `__webpack_public_path__`. + +```javascript +__webpack_public_path__ = myRuntimePublicPath; + +// rest of your application entry +``` + +See [this discussion](https://github.com/webpack/webpack/issues/2776#issuecomment-233208623) for more information on `__webpack_public_path__`. + + +## `output.sourceMapFilename` + +`string` + +This option is only used when [`devtool`](/configuration/devtool) uses a SourceMap option which writes an output file. + +Configure how source maps are named. By default `'[file].map'` is used. + +The `[name]`, `[id]`, `[hash]` and `[chunkhash]` substitutions from [#output-filename](#output-filename) can be used. In addition to those, you can use substitutions listed below. The `[file]` placeholder is replaced with the filename of the original file. We recommend __only using the `[file]` placeholder__, as the other placeholders won't work when generating SourceMaps for non-chunk files. + +| Template | Description | +| -------------------------- | ----------------------------------------------------------------------------------- | +| [file] | The module filename | +| [filebase] | The module [basename](https://nodejs.org/api/path.html#path_path_basename_path_ext) | + + +## `output.sourcePrefix` + +`string` + +Change the prefix for each line in the output bundles. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + sourcePrefix: '\t' + } +}; +``` + +Note by default an empty string is used. Using some kind of indentation makes bundles look more pretty, but will cause issues with multi-line strings. + +There is no need to change it. + + +## `output.strictModuleExceptionHandling` + +`boolean` + +Tell webpack to remove a module from the module instance cache (`require.cache`) if it throws an exception when it is `require`d. + +It defaults to `false` for performance reasons. + +When set to `false`, the module is not removed from cache, which results in the exception getting thrown only on the first `require` call (making it incompatible with node.js). + +For instance, consider `module.js`: + +```javascript +throw new Error('error'); +``` + +With `strictModuleExceptionHandling` set to `false`, only the first `require` throws an exception: + +```javascript +// with strictModuleExceptionHandling = false +require('module'); // <- throws +require('module'); // <- doesn't throw +``` + +Instead, with `strictModuleExceptionHandling` set to `true`, all `require`s of this module throw an exception: + +```javascript +// with strictModuleExceptionHandling = true +require('module'); // <- throws +require('module'); // <- also throws +``` + + +## `output.umdNamedDefine` + +`boolean` + +When using `libraryTarget: "umd"`, setting: + +```javascript +module.exports = { + //... + output: { + umdNamedDefine: true + } +}; +``` + +will name the AMD module of the UMD build. Otherwise an anonymous `define` is used. + + +# Module + +These options determine how the [different types of modules](/concepts/modules) within a project will be treated. + + +## `module.noParse` + +`RegExp | [RegExp] | function | string | [string]` + +Prevent webpack from parsing any files matching the given regular expression(s). Ignored files __should not__ have calls to `import`, `require`, `define` or any other importing mechanism. This can boost build performance when ignoring large libraries. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + noParse: /jquery|lodash/, + } +}; +``` + +```javascript +module.exports = { + //... + module: { + noParse: (content) => /jquery|lodash/.test(content) + } +}; +``` + + +## `module.rules` + +`[Rule]` + +An array of [Rules](#rule) which are matched to requests when modules are created. These rules can modify how the module is created. They can apply loaders to the module, or modify the parser. + + +## Rule + +`object` + +A Rule can be separated into three parts — Conditions, Results and nested Rules. + + +### Rule Conditions + +There are two input values for the conditions: + +1. The resource: An absolute path to the file requested. It's already resolved according to the [`resolve` rules](/configuration/resolve). + +2. The issuer: An absolute path to the file of the module which requested the resource. It's the location of the import. + +__Example:__ When we `import './style.css'` within `app.js`, the resource is `/path/to/style.css` and the issuer is `/path/to/app.js`. + +In a Rule the properties [`test`](#rule-test), [`include`](#rule-include), [`exclude`](#rule-exclude) and [`resource`](#rule-resource) are matched with the resource and the property [`issuer`](#rule-issuer) is matched with the issuer. + +When using multiple conditions, all conditions must match. + +W> Be careful! The resource is the _resolved_ path of the file, which means symlinked resources are the real path _not_ the symlink location. This is good to remember when using tools that symlink packages (like `npm link`), common conditions like `/node_modules/` may inadvertently miss symlinked files. Note that you can turn off symlink resolving (so that resources are resolved to the symlink path) via [`resolve.symlinks`](/configuration/resolve#resolve-symlinks). + + +### Rule results + +Rule results are used only when the Rule condition matches. + +There are two output values of a Rule: + +1. Applied loaders: An array of loaders applied to the resource. +2. Parser options: An options object which should be used to create the parser for this module. + +These properties affect the loaders: [`loader`](#rule-loader), [`options`](#rule-options-rule-query), [`use`](#rule-use). + +For compatibility also these properties: [`query`](#rule-options-rule-query), [`loaders`](#rule-loaders). + +The [`enforce`](#rule-enforce) property affects the loader category. Whether it's a normal, pre- or post- loader. + +The [`parser`](#rule-parser) property affects the parser options. + + +## Nested rules + +Nested rules can be specified under the properties [`rules`](#rule-rules) and [`oneOf`](#rule-oneof). + +These rules are evaluated when the Rule condition matches. + + +## `Rule.enforce` + +`string` + +Possible values: `'pre' | 'post'` + +Specifies the category of the loader. No value means normal loader. + +There is also an additional category "inlined loader" which are loaders applied inline of the import/require. + +There are two phases that all loaders enter one after the other: + +1. __Pitching__ phase: the pitch method on loaders is called in the order `post, inline, normal, pre`. See [Pitching Loader](/api/loaders/#pitching-loader) for details. +2. __Normal__ phase: the normal method on loaders is executed in the order `pre, normal, inline, post`. Transformation on the source code of a module happens in this phase. + +All normal loaders can be omitted (overridden) by prefixing `!` in the request. + +All normal and pre loaders can be omitted (overridden) by prefixing `-!` in the request. + +All normal, post and pre loaders can be omitted (overridden) by prefixing `!!` in the request. + +Inline loaders and `!` prefixes should not be used as they are non-standard. They may be use by loader generated code. + + +## `Rule.exclude` + +`Rule.exclude` is a shortcut to `Rule.resource.exclude`. If you supply a `Rule.exclude` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.exclude`](#condition) for details. + + +## `Rule.include` + +`Rule.include` is a shortcut to `Rule.resource.include`. If you supply a `Rule.include` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.include`](#condition) for details. + + +## `Rule.issuer` + +A [`Condition`](#condition) to match against the module that issued the request. In the following example, the `issuer` for the `a.js` request would be the path to the `index.js` file. + +__index.js__ + +```javascript +import A from './a.js'; +``` + +This option can be used to apply loaders to the dependencies of a specific module or set of modules. + + +## `Rule.loader` + +`Rule.loader` is a shortcut to `Rule.use: [ { loader } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.loader`](#useentry) for details. + + +## `Rule.loaders` + +W> This option is __deprecated__ in favor of `Rule.use`. + +`Rule.loaders` is an alias to `Rule.use`. See [`Rule.use`](#rule-use) for details. + + +## `Rule.oneOf` + +An array of [`Rules`](#rule) from which only the first matching Rule is used when the Rule matches. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + oneOf: [ + { + resourceQuery: /inline/, // foo.css?inline + use: 'url-loader' + }, + { + resourceQuery: /external/, // foo.css?external + use: 'file-loader' + } + ] + } + ] + } +}; +``` + +## `Rule.options` / `Rule.query` + +`Rule.options` and `Rule.query` are shortcuts to `Rule.use: [ { options } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.options`](#useentry) for details. + +W> `Rule.query` is deprecated in favor of `Rule.options` and `UseEntry.options`. + + +## `Rule.parser` + +An object with parser options. All applied parser options are merged. + +Parsers may inspect these options and disable or reconfigure themselves accordingly. Most of the default plugins interpret the values as follows: + +- Setting the option to `false` disables the parser. +- Setting the option to `true` or leaving it `undefined` enables the parser. + +However, parser plugins may accept more than just a boolean. For example, the internal `NodeStuffPlugin` can accept an object instead of `true` to add additional options for a particular Rule. + +__Examples__ (parser options by the default plugins): + +```js-with-links +module.exports = { + //... + module: { + rules: [ + { + //... + parser: { + amd: false, // disable AMD + commonjs: false, // disable CommonJS + system: false, // disable SystemJS + harmony: false, // disable ES2015 Harmony import/export + requireInclude: false, // disable require.include + requireEnsure: false, // disable require.ensure + requireContext: false, // disable require.context + browserify: false, // disable special handling of Browserify bundles + requireJs: false, // disable requirejs.* + node: false, // disable __dirname, __filename, module, require.extensions, require.main, etc. + node: {...} // reconfigure [node](/configuration/node) layer on module level + } + } + ] + } +} +``` + + +## `Rule.resource` + +A [`Condition`](#condition) matched with the resource. You can either supply a `Rule.resource` option or use the shortcut options `Rule.test`, `Rule.exclude`, and `Rule.include`. See details in [`Rule` conditions](#rule-conditions). + + +## `Rule.resourceQuery` + +A [`Condition`](#condition) matched with the resource query. This option is used to test against the query section of a request string (i.e. from the question mark onwards). If you were to `import Foo from './foo.css?inline'`, the following condition would match: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + resourceQuery: /inline/, + use: 'url-loader' + } + ] + } +}; +``` + + +## `Rule.rules` + +An array of [`Rules`](#rule) that is also used when the Rule matches. + + +## `Rule.sideEffects` + +`bool` + +Indicate what parts of the module contain side effects. See [Tree Shaking](/guides/tree-shaking/#mark-the-file-as-side-effect-free) for details. + + +## `Rule.test` + +`Rule.test` is a shortcut to `Rule.resource.test`. If you supply a `Rule.test` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.test`](#condition) for details. + + +## `Rule.type` + +`string` + +Possible values: `'javascript/auto' | 'javascript/dynamic' | 'javascript/esm' | 'json' | 'webassembly/experimental'` + +`Rule.type` sets the type for a matching module. This prevents defaultRules and their default importing behaviors from occurring. For example, if you want to load a `.json` file through a custom loader, you'd need to set the `type` to `javascript/auto` to bypass webpack's built-in json importing. (See [v4.0 changelog](https://github.com/webpack/webpack/releases/tag/v4.0.0) for more details) + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + //... + { + test: /\.json$/, + type: 'javascript/auto', + loader: 'custom-json-loader' + } + ] + } +}; +``` + + +## `Rule.use` + +A list of [UseEntries](#useentry) which are applied to modules. Each entry specifies a loader to be used. + +Passing a string (i.e. `use: [ 'style-loader' ]`) is a shortcut to the loader property (i.e. `use: [ { loader: 'style-loader '} ]`). + +Loaders can be chained by passing multiple loaders, which will be applied from right to left (last to first configured). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + //... + use: [ + 'style-loader', + { + loader: 'css-loader', + options: { + importLoaders: 1 + } + }, + { + loader: 'less-loader', + options: { + noIeCompat: true + } + } + ] + } + ] + } +}; +``` + +See [UseEntry](#useentry) for details. + + +## `Condition` + +Conditions can be one of these: + +- A string: To match the input must start with the provided string. I. e. an absolute directory path, or absolute path to the file. +- A RegExp: It's tested with the input. +- A function: It's called with the input and must return a truthy value to match. +- An array of Conditions: At least one of the Conditions must match. +- An object: All properties must match. Each property has a defined behavior. + +`{ test: Condition }`: The Condition must match. The convention is to provide a RegExp or array of RegExps here, but it's not enforced. + +`{ include: Condition }`: The Condition must match. The convention is to provide a string or array of strings here, but it's not enforced. + +`{ exclude: Condition }`: The Condition must NOT match. The convention is to provide a string or array of strings here, but it's not enforced. + +`{ and: [Condition] }`: All Conditions must match. + +`{ or: [Condition] }`: Any Condition must match. + +`{ not: [Condition] }`: All Conditions must NOT match. + +__Example:__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + include: [ + path.resolve(__dirname, 'app/styles'), + path.resolve(__dirname, 'vendor/styles') + ] + } + ] + } +}; +``` + + +## `UseEntry` + +`object` + +It must have a `loader` property being a string. It is resolved relative to the configuration [`context`](/configuration/entry-context#context) with the loader resolving options ([resolveLoader](/configuration/resolve#resolveloader)). + +It can have an `options` property being a string or object. This value is passed to the loader, which should interpret it as loader options. + +For compatibility a `query` property is also possible, which is an alias for the `options` property. Use the `options` property instead. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + loader: 'css-loader', + options: { + modules: true + } + } + ] + } +}; +``` + +Note that webpack needs to generate a unique module identifier from the resource and all loaders including options. It tries to do this with a `JSON.stringify` of the options object. This is fine in 99.9% of cases, but may be not unique if you apply the same loaders with different options to the resource and the options have some stringified values. + +It also breaks if the options object cannot be stringified (i.e. circular JSON). Because of this you can have a `ident` property in the options object which is used as unique identifier. + + +## Module Contexts + +> Avoid using these options as they are __deprecated__ and will soon be removed. + +These options describe the default settings for the context created when a dynamic dependency is encountered. + +Example for an `unknown` dynamic dependency: `require`. + +Example for an `expr` dynamic dependency: `require(expr)`. + +Example for an `wrapped` dynamic dependency: `require('./templates/' + expr)`. + +Here are the available options with their [defaults](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js): + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + exprContextCritical: true, + exprContextRecursive: true, + exprContextRegExp: false, + exprContextRequest: '.', + unknownContextCritical: true, + unknownContextRecursive: true, + unknownContextRegExp: false, + unknownContextRequest: '.', + wrappedContextCritical: false, + wrappedContextRecursive: true, + wrappedContextRegExp: /.*/, + strictExportPresence: false // since webpack 2.3.0 + } +}; +``` + +T> You can use the `ContextReplacementPlugin` to modify these values for individual dependencies. This also removes the warning. + +A few use cases: + +- Warn for dynamic dependencies: `wrappedContextCritical: true`. +- `require(expr)` should include the whole directory: `exprContextRegExp: /^\.\//` +- `require('./templates/' + expr)` should not include subdirectories by default: `wrappedContextRecursive: false` +- `strictExportPresence` makes missing exports an error instead of warning + + +# Resolve + +These options change how modules are resolved. webpack provides reasonable defaults, but it is possible to change the resolving in detail. Have a look at [Module Resolution](/concepts/module-resolution) for more explanation of how the resolver works. + + +## `resolve` + +`object` + +Configure how modules are resolved. For example, when calling `import "lodash"` in ES2015, the `resolve` options can change where webpack goes to look for `"lodash"` (see [`modules`](#resolve-modules)). + + +### `resolve.alias` + +`object` + +Create aliases to `import` or `require` certain modules more easily. For example, to alias a bunch of commonly used `src/` folders: + +```js +module.exports = { + //... + resolve: { + alias: { + Utilities: path.resolve(__dirname, 'src/utilities/'), + Templates: path.resolve(__dirname, 'src/templates/') + } + } +}; +``` + +Now, instead of using relative paths when importing like so: + +```js +import Utility from '../../utilities/utility'; +``` + +you can use the alias: + +```js +import Utility from 'Utilities/utility'; +``` + +A trailing `$` can also be added to the given object's keys to signify an exact match: + +```js +module.exports = { + //... + resolve: { + alias: { + xyz$: path.resolve(__dirname, 'path/to/file.js') + } + } +}; +``` + +which would yield these results: + +```js +import Test1 from 'xyz'; // Exact match, so path/to/file.js is resolved and imported +import Test2 from 'xyz/file.js'; // Not an exact match, normal resolution takes place +``` + +The following table explains other cases: + +| `alias:` | `import "xyz"` | `import "xyz/file.js"` | +| ----------------------------------- | ------------------------------------- | ----------------------------------- | +| `{}` | `/abc/node_modules/xyz/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | error | +| `{ xyz$: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "./dir/file.js" }` | `/abc/dir/file.js` | error | +| `{ xyz$: "./dir/file.js" }` | `/abc/dir/file.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "/some/dir" }` | `/some/dir/index.js` | `/some/dir/file.js` | +| `{ xyz$: "/some/dir" }` | `/some/dir/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "./dir" }` | `/abc/dir/index.js` | `/abc/dir/file.js` | +| `{ xyz: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/modu/file.js` | +| `{ xyz$: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "modu/some/file.js" }` | `/abc/node_modules/modu/some/file.js` | error | +| `{ xyz: "modu/dir" }` | `/abc/node_modules/modu/dir/index.js` | `/abc/node_modules/dir/file.js` | +| `{ xyz: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/dir/file.js` | +| `{ xyz$: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/file.js` | + +`index.js` may resolve to another file if defined in the `package.json`. + +`/abc/node_modules` may resolve in `/node_modules` too. + + +### `resolve.aliasFields` + +`array` + +Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec). Default: + +```js +module.exports = { + //... + resolve: { + aliasFields: ['browser'] + } +}; +``` + + +### `resolve.cacheWithContext` + +`boolean` (since webpack 3.1.0) + +If unsafe cache is enabled, includes `request.context` in the cache key. This option is taken into account by the [`enhanced-resolve`](https://github.com/webpack/enhanced-resolve/) module. Since webpack 3.1.0 context in resolve caching is ignored when resolve or resolveLoader plugins are provided. This addresses a performance regression. + + +### `resolve.descriptionFiles` + +`array` + +The JSON files to use for descriptions. Default: + +```js +module.exports = { + //... + resolve: { + descriptionFiles: ['package.json'] + } +}; +``` + + +### `resolve.enforceExtension` + +`boolean` + +If `true`, it will not allow extension-less files. So by default `require('./foo')` works if `./foo` has a `.js` extension, but with this enabled only `require('./foo.js')` will work. Default: + +```js +module.exports = { + //... + resolve: { + enforceExtension: false + } +}; +``` + + +### `resolve.enforceModuleExtension` + +`boolean` + +Whether to require to use an extension for modules (e.g. loaders). Default: + +```js +module.exports = { + //... + resolve: { + enforceModuleExtension: false + } +}; +``` + + +### `resolve.extensions` + +`array` + +Automatically resolve certain extensions. This defaults to: + +```js +module.exports = { + //... + resolve: { + extensions: ['.wasm', '.mjs', '.js', '.json'] + } +}; +``` + +which is what enables users to leave off the extension when importing: + +```js +import File from '../path/to/file'; +``` + +W> Using this will __override the default array__, meaning that webpack will no longer try to resolve modules using the default extensions. For modules that are imported with their extension, e.g. `import SomeFile from "./somefile.ext"`, to be properly resolved, a string containing "\*" must be included in the array. + + +### `resolve.mainFields` + +`array` + +When importing from an npm package, e.g. `import * as D3 from "d3"`, this option will determine which fields in its `package.json` are checked. The default values will vary based upon the [`target`](/concepts/targets) specified in your webpack configuration. + +When the `target` property is set to `webworker`, `web`, or left unspecified: + + +```js +module.exports = { + //... + resolve: { + mainFields: ['browser', 'module', 'main'] + } +}; +``` + +For any other target (including `node`): + +```js +module.exports = { + //... + resolve: { + mainFields: ['module', 'main'] + } +}; +``` + +For example, the `package.json` of [D3](https://d3js.org/) contains these fields: + +```json +{ + "main": "build/d3.Node.js", + "browser": "build/d3.js", + "module": "index" +} +``` + +This means that when we `import * as D3 from "d3"` this will really resolve to the file in the `browser` property. The `browser` property takes precedence here because it's the first item in `mainFields`. Meanwhile, a Node.js application bundled by webpack will resolve by default to the file in the `module` field. + + +### `resolve.mainFiles` + +`array` + +The filename to be used while resolving directories. Default: + +```js +module.exports = { + //... + resolve: { + mainFiles: ['index'] + } +}; +``` + + +### `resolve.modules` + +`array` + +Tell webpack what directories should be searched when resolving modules. + +Absolute and relative paths can both be used, but be aware that they will behave a bit differently. + +A relative path will be scanned similarly to how Node scans for `node_modules`, by looking through the current directory as well as its ancestors (i.e. `./node_modules`, `../node_modules`, and on). + +With an absolute path, it will only search in the given directory. + +`resolve.modules` defaults to: + +```js +module.exports = { + //... + resolve: { + modules: ['node_modules'] + } +}; +``` + +If you want to add a directory to search in that takes precedence over `node_modules/`: + +```js +module.exports = { + //... + resolve: { + modules: [path.resolve(__dirname, 'src'), 'node_modules'] + } +}; +``` + + +### `resolve.unsafeCache` + +`regex` `array` `boolean` + +Enable aggressive, but __unsafe__, caching of modules. Passing `true` will cache everything. Default: + +```js +module.exports = { + //... + resolve: { + unsafeCache: true + } +}; +``` + +A regular expression, or an array of regular expressions, can be used to test file paths and only cache certain modules. For example, to only cache utilities: + +```js +module.exports = { + //... + resolve: { + unsafeCache: /src\/utilities/ + } +}; +``` + +W> Changes to cached paths may cause failure in rare cases. + + +### `resolve.plugins` + +A list of additional resolve plugins which should be applied. It allows plugins such as [`DirectoryNamedWebpackPlugin`](https://www.npmjs.com/package/directory-named-webpack-plugin). + +```js +module.exports = { + //... + resolve: { + plugins: [ + new DirectoryNamedWebpackPlugin() + ] + } +}; +``` + + +### `resolve.symlinks` + +`boolean` + +Whether to resolve symlinks to their symlinked location. + +When enabled, symlinked resources are resolved to their _real_ path, not their symlinked location. Note that this may cause module resolution to fail when using tools that symlink packages (like `npm link`). + +`resolve.symlinks` defaults to: + +```js +module.exports = { + //... + resolve: { + symlinks: true + } +}; +``` + + +### `resolve.cachePredicate` + +`function` + +A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. Default: + +```js +module.exports = { + //... + resolve: { + cachePredicate: function() { return true; } + } +}; +``` + + +## `resolveLoader` + +`object` + +This set of options is identical to the `resolve` property set above, but is used only to resolve webpack's [loader](/concepts/loaders) packages. Default: + +```js +module.exports = { + //... + resolveLoader: { + modules: [ 'node_modules' ], + extensions: [ '.js', '.json' ], + mainFields: [ 'loader', 'main' ] + } +}; +``` + +T> Note that you can use alias here and other features familiar from resolve. For example `{ txt: 'raw-loader' }` would shim `txt!templates/demo.txt` to use `raw-loader`. + + +### `resolveLoader.moduleExtensions` + +`array` + +The extensions/suffixes that are used when resolving loaders. Since version two, we [strongly recommend](/migrate/3/#automatic-loader-module-name-extension-removed) using the full name, e.g. `example-loader`, as much as possible for clarity. However, if you really wanted to exclude the `-loader` bit, i.e. just use `example`, you can use this option to do so: + +```js +module.exports = { + //... + resolveLoader: { + moduleExtensions: [ '-loader' ] + } +}; +``` + + +# Optimization + +Since version 4 webpack runs optimizations for you depending on the chosen [`mode`](/concepts/mode/), still all optimizations are available for manual configuration and overrides. + + +## `optimization.minimize` + +`boolean` + +Tell webpack to minimize the bundle using the [TerserPlugin](/plugins/terser-webpack-plugin/). + +This is `true` by default in `production` mode. + +__webpack.config.js__ + + +```js +module.exports = { + //... + optimization: { + minimize: false + } +}; +``` + +T> Learn how [mode](/concepts/mode/) works. + +## `optimization.minimizer` + +`[TerserPlugin]` + +Allows you to override the default minimizer by providing a different one or more customized [TerserPlugin](/plugins/terser-webpack-plugin/) instances. + +__webpack.config.js__ + + +```js +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + //... + optimization: { + minimizer: [ + new TerserPlugin({ /* your config */ }) + ] + } +}; +``` + +## `optimization.splitChunks` + +`object` + +By default webpack v4+ provides new common chunks strategies out of the box for dynamically imported modules. See available options for configuring this behavior in the [SplitChunksPlugin](/plugins/split-chunks-plugin/) page. + +## `optimization.runtimeChunk` + +`object` `string` `boolean` + +Setting `optimization.runtimeChunk` to `true` or `"multiple"` adds an additional chunk to each entrypoint containing only the runtime. This setting is an alias for: + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: entrypoint => `runtime~${entrypoint.name}` + } + } +}; +``` + +The value `"single"` instead creates a runtime file to be shared for all generated chunks. This setting is an alias for: + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: 'runtime' + } + } +}; +``` + +By setting `optimization.runtimeChunk` to `object` it is only possible to provide the `name` property which stands for the name or name factory for the runtime chunks. + +Default is `false`: each entry chunk embeds runtime. + +W> Imported modules are initialized for each runtime chunk separately, so if you include multiple entry points on a page, beware of this behavior. You will probably want to set it to `single` or use another configuration that allows you to only have one runtime instance. + +__webpack.config.js__ + + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: entrypoint => `runtimechunk~${entrypoint.name}` + } + } +}; +``` + +## `optimization.noEmitOnErrors` + +`boolean` + +Use the `optimization.noEmitOnErrors` to skip the emitting phase whenever there are errors while compiling. This ensures that no erroring assets are emitted. The `emitted` flag in the stats is `false` for all assets. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + noEmitOnErrors: true + } +}; +``` + +W> If you are using webpack [CLI](/api/cli/), the webpack process will not exit with an error code while this plugin is enabled. If you want webpack to "fail" when using the CLI, please check out the [`bail` option](/api/cli/#advanced-options). + +## `optimization.namedModules` + +`boolean: false` + +Tells webpack to use readable module identifiers for better debugging. When `optimization.namedModules` is not set in webpack config, webpack will enable it by default for [mode](/concepts/mode/) `development` and disable for [mode](/concepts/mode/) `production`. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + namedModules: true + } +}; +``` + +## `optimization.namedChunks` + +`boolean: false` + +Tells webpack to use readable chunk identifiers for better debugging. This option is enabled by default for [mode](/concepts/mode/) `development` and disabled for [mode](/concepts/mode/) `production` if no option is provided in webpack config. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + namedChunks: true + } +}; +``` + +## `optimization.moduleIds` + +`bool: false` `string: natural, named, hashed, size, total-size` + +Tells webpack which algorithm to use when choosing module ids. Setting `optimization.moduleIds` to `false` tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin. By default `optimization.moduleIds` is set to `false`. + +The following string values are supported: + +Option | Description +--------------------- | ----------------------- +`natural` | Numeric ids in order of usage. +`named` | Readable ids for better debugging. +`hashed` | Short hashes as ids for better long term caching. +`size` | Numeric ids focused on minimal initial download size. +`total-size` | numeric ids focused on minimal total download size. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + moduleIds: 'hashed' + } +}; +``` + +## `optimization.nodeEnv` + +`string` `bool: false` + +Tells webpack to set `process.env.NODE_ENV` to a given string value. `optimization.nodeEnv` uses [DefinePlugin](/plugins/define-plugin/) unless set to `false`. `optimization.nodeEnv` __defaults__ to [mode](/concepts/mode/) if set, else falls back to `"production"`. + +Possible values: + +- any string: the value to set `process.env.NODE_ENV` to. +- false: do not modify/set the value of `process.env.NODE_ENV`. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + nodeEnv: 'production' + } +}; +``` + +## `optimization.mangleWasmImports` + +`bool: false` + +When set to `true` tells webpack to reduce the size of WASM by changing imports to shorter strings. It mangles module and export names. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + mangleWasmImports: true + } +}; +``` + +## `optimization.removeAvailableModules` + +`bool: true` + +Tells webpack to detect and remove modules from chunks when these modules are already included in all parents. Setting `optimization.removeAvailableModules` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + removeAvailableModules: false + } +}; +``` + +## `optimization.removeEmptyChunks` + +`bool: true` + +Tells webpack to detect and remove chunks which are empty. Setting `optimization.removeEmptyChunks` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + removeEmptyChunks: false + } +}; +``` + +## `optimization.mergeDuplicateChunks` + +`bool: true` + +Tells webpack to merge chunks which contain the same modules. Setting `optimization.mergeDuplicateChunks` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + mergeDuplicateChunks: false + } +}; +``` + +## `optimization.flagIncludedChunks` + +`bool` + +Tells webpack to determine and flag chunks which are subsets of other chunks in a way that subsets don’t have to be loaded when the bigger chunk has been already loaded. By default `optimization.flagIncludedChunks` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + flagIncludedChunks: true + } +}; +``` + +## `optimization.occurrenceOrder` + +`bool` + +Tells webpack to figure out an order of modules which will result in the smallest initial bundle. By default `optimization.occurrenceOrder` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + occurrenceOrder: false + } +}; +``` + +## `optimization.providedExports` + +`bool` + +Tells webpack to figure out which exports are provided by modules to generate more efficient code for `export * from ...`. By default `optimization.providedExports` is enabled. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + providedExports: false + } +}; +``` + +## `optimization.usedExports` + +`bool` + +Tells webpack to determine used exports for each module. This depends on [`optimization.providedExports`](#optimization-occurrenceorder). Information collected by `optimization.usedExports` is used by other optimizations or code generation i.e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible. +Dead code elimination in minimizers will benefit from this and can remove unused exports. +By default `optimization.usedExports` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + usedExports: true + } +}; +``` + +## `optimization.concatenateModules` + +`bool` + +Tells webpack to find segments of the module graph which can be safely concatenated into a single module. Depends on [`optimization.providedExports`](#optimization-providedexports) and [`optimization.usedExports`](#optimization-usedexports). +By default `optimization.concatenateModules` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + concatenateModules: true + } +}; +``` + +## `optimization.sideEffects` + +`bool` + +Tells webpack to recognise the [`sideEffects`](https://github.com/webpack/webpack/blob/master/examples/side-effects/README.md) flag in `package.json` or rules to skip over modules which are flagged to contain no side effects when exports are not used. + +__package.json__ + +``` json +{ + "name": "awesome npm module", + "version": "1.0.0", + "sideEffects": false +} +``` + +T> Please note that `sideEffects` should be in the npm module's `package.json` file and doesn't mean that you need to set `sideEffects` to `false` in your own project's `package.json` which requires that big module. + +`optimization.sideEffects` depends on [`optimization.providedExports`](#optimization-providedexports) to be enabled. This dependency has a build time cost, but eliminating modules has positive impact on performance because of less code generation. Effect of this optimization depends on your codebase, try it for possible performance wins. + +By default `optimization.sideEffects` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + sideEffects: true + } +}; +``` + +## `optimization.portableRecords` + +`bool` + +`optimization.portableRecords` tells webpack to generate records with relative paths to be able to move the context folder. + +By default `optimization.portableRecords` is disabled. Automatically enabled if at least one of the records options provided to webpack config: [`recordsPath`](/configuration/other-options/#recordspath), [`recordsInputPath`](/configuration/other-options/#recordsinputpath), [`recordsOutputPath`](/configuration/other-options/#recordsoutputpath). + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + portableRecords: true + } +}; +``` + + +# Plugins + +The `plugins` option is used to customize the webpack build process in a variety of ways. webpack comes with a variety built-in plugins available under `webpack.[plugin-name]`. See [Plugins page](/plugins) for a list of plugins and documentation but note that there are a lot more out in the community. + +T> Note: This page only discusses using plugins, however if you are interested in writing your own please visit [Writing a Plugin](/development/how-to-write-a-plugin/). + + +## `plugins` + +`array` + +A list of webpack plugins. For example, [`DefinePlugin`](/plugins/define-plugin/) allows you to create global constants which can be configured at compile time. This can be useful for allowing different behavior between development builds and release builds. + +```js +module.exports = { + //... + plugins: [ + new webpack.DefinePlugin({ + // Definitions... + }) + ] +}; +``` + +A more complex example, using multiple plugins, might look something like this: + +```js +var webpack = require('webpack'); +// importing plugins that do not come by default in webpack +var ExtractTextPlugin = require('extract-text-webpack-plugin'); +var DashboardPlugin = require('webpack-dashboard/plugin'); + +// adding plugins to your configuration +module.exports = { + //... + plugins: [ + new ExtractTextPlugin({ + filename: 'build.min.css', + allChunks: true, + }), + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + // compile time plugins + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': '"production"', + }), + // webpack-dev-server enhancement plugins + new DashboardPlugin(), + new webpack.HotModuleReplacementPlugin(), + ] +}; +``` + + +# DevServer + +[webpack-dev-server](https://github.com/webpack/webpack-dev-server) can be used to quickly develop an application. See the [development guide](/guides/development/) to get started. + +This page describes the options that affect the behavior of webpack-dev-server (short: dev-server). + +T> Options that are compatible with [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) have 🔑 next to them. + + +## `devServer` + +`object` + +This set of options is picked up by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) and can be used to change its behavior in various ways. Here's a simple example that gzips and serves everything from our `dist/` directory in the project root: + +__webpack.config.js__ + +```javascript +var path = require('path'); + +module.exports = { + //... + devServer: { + contentBase: path.join(__dirname, 'dist'), + compress: true, + port: 9000 + } +}; +``` + +When the server is started, there will be a message prior to the list of resolved modules: + +```bash +http://localhost:9000/ +webpack output is served from /build/ +Content not from webpack is served from /path/to/dist/ +``` + +that will give some background on where the server is located and what it's serving. + +If you're using dev-server through the Node.js API, the options in `devServer` will be ignored. Pass the options as a second parameter instead: `new WebpackDevServer(compiler, {...})`. [See here](https://github.com/webpack/webpack-dev-server/tree/master/examples/api/simple) for an example of how to use webpack-dev-server through the Node.js API. + +W> Be aware that when [exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) only the `devServer` options for the first configuration will be taken into account and used for all the configurations in the array. + +T> If you're having trouble, navigating to the `/webpack-dev-server` route will show where files are served. For example, `http://localhost:9000/webpack-dev-server`. + +## `devServer.after` + +`function (app, server)` + +Provides the ability to execute custom middleware after all other middleware +internally within the server. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + after: function(app, server) { + // do fancy stuff + } + } +}; +``` + +## `devServer.allowedHosts` + +`array` + +This option allows you to whitelist services that are allowed to access the dev server. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + allowedHosts: [ + 'host.com', + 'subdomain.host.com', + 'subdomain2.host.com', + 'host2.com' + ] + } +}; +``` + +Mimicking django's `ALLOWED_HOSTS`, a value beginning with `.` can be used as a subdomain wildcard. `.host.com` will match `host.com`, `www.host.com`, and any other subdomain of `host.com`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + // this achieves the same effect as the first example + // with the bonus of not having to update your config + // if new subdomains need to access the dev server + allowedHosts: [ + '.host.com', + 'host2.com' + ] + } +}; +``` + +To use this option with the CLI pass the `--allowed-hosts` option a comma-delimited string. + +```bash +webpack-dev-server --entry /entry/file --output-path /output/path --allowed-hosts .host.com,host2.com +``` + +## `devServer.before` + +`function (app, server)` + +Provides the ability to execute custom middleware prior to all other middleware +internally within the server. This could be used to define custom handlers, for +example: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + before: function(app, server) { + app.get('/some/path', function(req, res) { + res.json({ custom: 'response' }); + }); + } + } +}; +``` + +## `devServer.bonjour` + +This option broadcasts the server via [ZeroConf](http://www.zeroconf.org/) networking on start + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + bonjour: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --bonjour +``` + + +## `devServer.clientLogLevel` + +`string: 'none' | 'info' | 'error' | 'warning'` + +When using _inline mode_, the console in your DevTools will show you messages e.g. before reloading, before an error or when [Hot Module Replacement](/concepts/hot-module-replacement/) is enabled. Defaults to `info`. + +`devServer.clientLogLevel` may be too verbose, you can turn logging off by setting it to `'none'`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + clientLogLevel: 'none' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --client-log-level none +``` + +## `devServer.color` - CLI only + +`boolean` + +Enables/Disables colors on the console. + +```bash +webpack-dev-server --color +``` + + +## `devServer.compress` + +`boolean` + +Enable [gzip compression](https://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/) for everything served: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + compress: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --compress +``` + + +## `devServer.contentBase` + +`boolean: false` `string` `[string]` `number` + +Tell the server where to serve content from. This is only necessary if you want to serve static files. [`devServer.publicPath`](#devserver-publicpath-) will be used to determine where the bundles should be served from, and takes precedence. + +T> It is recommended to use an absolute path. + +By default it will use your current working directory to serve content. To disable `contentBase` set it to `false`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + contentBase: path.join(__dirname, 'public') + } +}; +``` + +It is also possible to serve from multiple directories: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + contentBase: [path.join(__dirname, 'public'), path.join(__dirname, 'assets')] + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --content-base /path/to/content/dir +``` + + +## `devServer.disableHostCheck` + +`boolean` + +When set to `true` this option bypasses host checking. __THIS IS NOT RECOMMENDED__ as apps that do not check the host are vulnerable to DNS rebinding attacks. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + disableHostCheck: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --disable-host-check +``` + + +## `devServer.filename` 🔑 + +`string` + +This option lets you reduce the compilations in [lazy mode](#devserver-lazy-). +By default in [lazy mode](#devserver-lazy-), every request results in a new compilation. With `filename`, it's possible to only compile when a certain file is requested. + +If [`output.filename`](/configuration/output/#output-filename) is set to `'bundle.js'` and `devServer.filename` is used like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: 'bundle.js' + }, + devServer: { + lazy: true, + filename: 'bundle.js' + } +}; +``` + +It will now only compile the bundle when `/bundle.js` is requested. + +T> `filename` has no effect when used without [lazy mode](#devserver-lazy-). + + +## `devServer.headers` 🔑 + +`object` + +Adds headers to all responses: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + headers: { + 'X-Custom-Foo': 'bar' + } + } +}; +``` + + +## `devServer.historyApiFallback` + +`boolean` `object` + +When using the [HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/API/History), the `index.html` page will likely have to be served in place of any `404` responses. `devServer.historyApiFallback` is disabled by default. Enable it by passing: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: true + } +}; +``` + +By passing an object this behavior can be controlled further using options like `rewrites`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: { + rewrites: [ + { from: /^\/$/, to: '/views/landing.html' }, + { from: /^\/subpage/, to: '/views/subpage.html' }, + { from: /./, to: '/views/404.html' } + ] + } + } +}; +``` + +When using dots in your path (common with Angular), you may need to use the `disableDotRule`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: { + disableDotRule: true + } + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --history-api-fallback +``` + +For more options and information, see the [connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback) documentation. + + +## `devServer.host` + +`string` + +Specify a host to use. By default this is `localhost`. If you want your server to be accessible externally, specify it like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + host: '0.0.0.0' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --host 0.0.0.0 +``` + + +## `devServer.hot` + +`boolean` + +Enable webpack's [Hot Module Replacement](/concepts/hot-module-replacement/) feature: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + hot: true + } +}; +``` + +T> Note that [`webpack.HotModuleReplacementPlugin`](/plugins/hot-module-replacement-plugin/) is required to fully enable HMR. If `webpack` or `webpack-dev-server` are launched with the `--hot` option, this plugin will be added automatically, so you may not need to add this to your `webpack.config.js`. See the [HMR concepts page](/concepts/hot-module-replacement/) for more information. + + +## `devServer.hotOnly` + +`boolean` + +Enables Hot Module Replacement (see [`devServer.hot`](#devserver-hot)) without page refresh as fallback in case of build failures. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + hotOnly: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --hot-only +``` + + +## `devServer.https` + +`boolean` `object` + +By default dev-server will be served over HTTP. It can optionally be served over HTTP/2 with HTTPS: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + https: true + } +}; +``` + +With the above setting a self-signed certificate is used, but you can provide your own: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + https: { + key: fs.readFileSync('/path/to/server.key'), + cert: fs.readFileSync('/path/to/server.crt'), + ca: fs.readFileSync('/path/to/ca.pem'), + } + } +}; +``` + +This object is passed straight to Node.js HTTPS module, so see the [HTTPS documentation](https://nodejs.org/api/https.html) for more information. + +Usage via the CLI + +```bash +webpack-dev-server --https +``` + +To pass your own certificate via the CLI use the following options + +```bash +webpack-dev-server --https --key /path/to/server.key --cert /path/to/server.crt --cacert /path/to/ca.pem +``` + +## `devServer.index` + +`string` + +The filename that is considered the index file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + index: 'index.html' + } +}; +``` + + +## `devServer.info` - CLI only + +`boolean` + +Output cli information. It is enabled by default. + +```bash +webpack-dev-server --info=false +``` + + +## `devServer.inline` + +`boolean` + +Toggle between the dev-server's two different modes. By default the application will be served with _inline mode_ enabled. This means that a script will be inserted in your bundle to take care of live reloading, and build messages will appear in the browser console. + +It is also possible to use __iframe mode__, which uses an `<iframe>` under a notification bar with messages about the build. To switch to __iframe mode__: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + inline: false + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --inline=false +``` + +T> Inline mode is recommended for [Hot Module Replacement](/plugins/hot-module-replacement-plugin/) as it includes an HMR trigger from the websocket. Polling mode can be used as an alternative, but requires an additional entry point, `'webpack/hot/poll?1000'`. + + +## `devServer.lazy` 🔑 + +`boolean` + +When `devServer.lazy` is enabled, the dev-server will only compile the bundle when it gets requested. This means that webpack will not watch any file changes. We call this __lazy mode__. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + lazy: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --lazy +``` + +T> [`watchOptions`](#devserver-watchoptions-) will have no effect when used with __lazy mode__. + +T> If you use the CLI, make sure __inline mode__ is disabled. + + +## `devServer.noInfo` 🔑 + +`boolean` + +Tells dev-server to supress messages like the webpack bundle information. Errors and warnings will still be shown. `devServer.noInfo` is disabled by default. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + noInfo: true + } +}; +``` + + +## `devServer.open` + +`boolean` `string` + +Tells dev-server to open the browser after server had been started. Disabled by default. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + open: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --open +``` + +If no browser is provided (as shown above), your default browser will be used. To specify a different browser, just pass its name: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + open: 'Chrome' + } +}; +``` + +And via the CLI + +```bash +webpack-dev-server --open 'Chrome' +``` + +T> The browser application name is platform dependent. Don't hard code it in reusable modules. For example, `'Chrome'` is Google Chrome on macOS, `'google-chrome'` on Linux and `'chrome'` on Windows. + + +## `devServer.openPage` + +`string` + +Specify a page to navigate to when opening the browser. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + openPage: '/different/page' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --open-page "/different/page" +``` + + +## `devServer.overlay` + +`boolean` `object: { boolean errors, boolean warnings }` + +Shows a full-screen overlay in the browser when there are compiler errors or warnings. Disabled by default. If you want to show only compiler errors: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + overlay: true + } +}; +``` + +If you want to show warnings as well as errors: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + overlay: { + warnings: true, + errors: true + } + } +}; +``` + + +## `devServer.pfx` + +`string` + +When used via the CLI, a path to an SSL .pfx file. If used in options, it should be the bytestream of the .pfx file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + pfx: '/path/to/file.pfx' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --pfx /path/to/file.pfx +``` + + +## `devServer.pfxPassphrase` + +`string` + +The passphrase to a SSL PFX file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + pfxPassphrase: 'passphrase' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --pfx-passphrase passphrase +``` + + +## `devServer.port` + +`number` + +Specify a port number to listen for requests on: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + port: 8080 + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --port 8080 +``` + + +## `devServer.proxy` + +`object` `[object, function]` + +Proxying some URLs can be useful when you have a separate API backend development server and you want to send API requests on the same domain. + +The dev-server makes use of the powerful [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) package. Check out its [documentation](https://github.com/chimurai/http-proxy-middleware#options) for more advanced usages. Note that some of `http-proxy-middleware`'s features do not require a `target` key, e.g. its `router` feature, but you will still need to include a `target` key in your config here, otherwise `webpack-dev-server` won't pass it along to `http-proxy-middleware`). + +With a backend on `localhost:3000`, you can use this to enable proxying: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': 'http://localhost:3000' + } + } +}; +``` + +A request to `/api/users` will now proxy the request to `http://localhost:3000/api/users`. + +If you don't want `/api` to be passed along, we need to rewrite the path: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'http://localhost:3000', + pathRewrite: {'^/api' : ''} + } + } + } +}; +``` + +A backend server running on HTTPS with an invalid certificate will not be accepted by default. If you want to, modify your config like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'https://other-server.example.com', + secure: false + } + } + } +}; +``` + +Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a function. + +In the function you get access to the request, response and proxy options. It must return either `false` or a path that will be served instead of continuing to proxy the request. + +E.g. for a browser request, you want to serve a HTML page, but for an API request you want to proxy it. You could do something like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'http://localhost:3000', + bypass: function(req, res, proxyOptions) { + if (req.headers.accept.indexOf('html') !== -1) { + console.log('Skipping proxy for browser request.'); + return '/index.html'; + } + } + } + } + } +}; +``` + +If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a `context` property: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: [{ + context: ['/auth', '/api'], + target: 'http://localhost:3000', + }] + } +}; +``` + +Note that requests to root won't be proxied by default. To enable root proxying, the `devServer.index` option should be specified as a falsy value: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + index: '', // specify to enable root proxying + host: '...', + contentBase: '...', + proxy: { + context: () => true, + target: 'http://localhost:1234' + } + } +}; +``` + +The origin of the host header is kept when proxying by default, you can set `changeOrigin` to `true` to override this behaviour. It is useful in some cases like using [name-based virtual hosted sites](https://en.wikipedia.org/wiki/Virtual_hosting#Name-based). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': 'http://localhost:3000', + changeOrigin: true + } + } +}; +``` + +## `devServer.progress` - CLI only + +`boolean` + +Output running progress to console. + +```bash +webpack-dev-server --progress +``` + + +## `devServer.public` + +`string` + +When using _inline mode_ and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on `window.location`, but if that fails you'll need to use this. + +For example, the dev-server is proxied by nginx, and available on `myapp.test`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + public: 'myapp.test:80' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --public myapp.test:80 +``` + + +## `devServer.publicPath` 🔑 + +`string` + +The bundled files will be available in the browser under this path. + +Imagine that the server is running under `http://localhost:8080` and [`output.filename`](/configuration/output/#output-filename) is set to `bundle.js`. By default the `devServer.publicPath` is `'/'`, so your bundle is available as `http://localhost:8080/bundle.js`. + +Change `devServer.publicPath` to put bundle under specific directory: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + publicPath: '/assets/' + } +}; +``` + +The bundle will now be available as `http://localhost:8080/assets/bundle.js`. + +T> Make sure `devServer.publicPath` always starts and ends with a forward slash. + +It is also possible to use a full URL. This is necessary for [Hot Module Replacement](/concepts/hot-module-replacement/). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + publicPath: 'http://localhost:8080/assets/' + } +}; +``` + +The bundle will also be available as `http://localhost:8080/assets/bundle.js`. + +T> It is recommended that `devServer.publicPath` is the same as [`output.publicPath`](/configuration/output/#output-publicpath). + + +## `devServer.quiet` 🔑 + +`boolean` + +With `devServer.quiet` enabled, nothing except the initial startup information will be written to the console. This also means that errors or warnings from webpack are not visible. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + quiet: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --quiet +``` + + +## `devServer.setup` + +`function (app, server)` + +W> This option is __deprecated__ in favor of [`devServer.before`](#devserver-before) and will be removed in v3.0.0. + +Here you can access the Express app object and add your own custom middleware to it. +For example, to define custom handlers for some paths: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + setup: function(app, server) { + app.get('/some/path', function(req, res) { + res.json({ custom: 'response' }); + }); + } + } +}; +``` + + +## `devServer.socket` + +`string` + +The Unix socket to listen to (instead of a host). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + socket: 'socket' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --socket socket +``` + + +## `devServer.staticOptions` + +It is possible to configure advanced options for serving static files from `contentBase`. See the [Express documentation](http://expressjs.com/en/4x/api.html#express.static) for the possible options. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + staticOptions: { + redirect: false + } + } +}; +``` + +T> This only works when using [`devServer.contentBase`](#devserver-contentbase) as a `string`. + + +## `devServer.stats` 🔑 + +`string: 'none' | 'errors-only' | 'minimal' | 'normal' | 'verbose'` `object` + +This option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you want some bundle information, but not all of it. + +To show only errors in your bundle: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + stats: 'errors-only' + } +}; +``` + +For more information, see the [__stats documentation__](/configuration/stats/). + +T> This option has no effect when used with `quiet` or `noInfo`. + + +## `devServer.stdin` - CLI only + +`boolean` + +This option closes the server when stdin ends. + +```bash +webpack-dev-server --stdin +``` + + +## `devServer.useLocalIp` + +`boolean` + +This option lets the browser open with your local IP. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + useLocalIp: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --useLocalIp +``` + + +## `devServer.watchContentBase` + +`boolean` + +Tell dev-server to watch the files served by the [`devServer.contentBase`](#devserver-contentbase) option. It is disabled by default. When enabled, file changes will trigger a full page reload. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + watchContentBase: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --watch-content-base +``` + + +## `devServer.watchOptions` 🔑 + +`object` + +Control options related to watching the files. + +webpack uses the file system to get notified of file changes. In some cases this does not work. For example, when using Network File System (NFS). [Vagrant](https://www.vagrantup.com/) also has a lot of problems with this. In these cases, use polling: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + watchOptions: { + poll: true + } + } +}; +``` + +If this is too heavy on the file system, you can change this to an integer to set the interval in milliseconds. + +See [WatchOptions](/configuration/watch/) for more options. + + +# Devtool + +This option controls if and how source maps are generated. + +Use the [`SourceMapDevToolPlugin`](/plugins/source-map-dev-tool-plugin) for a more fine grained configuration. See the [`source-map-loader`](/loaders/source-map-loader) to deal with existing source maps. + + +## `devtool` + +`string` `false` + +Choose a style of [source mapping](http://blog.teamtreehouse.com/introduction-source-maps) to enhance the debugging process. These values can affect build and rebuild speed dramatically. + +T> The webpack repository contains an [example showing the effect of all `devtool` variants](https://github.com/webpack/webpack/tree/master/examples/source-map). Those examples will likely help you to understand the differences. + +T> Instead of using the `devtool` option you can also use `SourceMapDevToolPlugin`/`EvalSourceMapDevToolPlugin` directly as it has more options. Never use both the `devtool` option and plugin together. The `devtool` option adds the plugin internally so you would end up with the plugin applied twice. + +devtool | build | rebuild | production | quality +------------------------------ | ----- | ------- | ---------- | ----------------------------- +(none) | +++ | +++ | yes | bundled code +eval | +++ | +++ | no | generated code +cheap-eval-source-map | + | ++ | no | transformed code (lines only) +cheap-module-eval-source-map | o | ++ | no | original source (lines only) +eval-source-map | -- | + | no | original source +cheap-source-map | + | o | yes | transformed code (lines only) +cheap-module-source-map | o | - | yes | original source (lines only) +inline-cheap-source-map | + | o | no | transformed code (lines only) +inline-cheap-module-source-map | o | - | no | original source (lines only) +source-map | -- | -- | yes | original source +inline-source-map | -- | -- | no | original source +hidden-source-map | -- | -- | yes | original source +nosources-source-map | -- | -- | yes | without source content + +T> `+++` super fast, `++` fast, `+` pretty fast, `o` medium, `-` pretty slow, `--` slow + +Some of these values are suited for development and some for production. For development you typically want fast Source Maps at the cost of bundle size, but for production you want separate Source Maps that are accurate and support minimizing. + +W> There are some issues with Source Maps in Chrome. [We need your help!](https://github.com/webpack/webpack/issues/3165). + +T> See [`output.sourceMapFilename`](/configuration/output#output-sourcemapfilename) to customize the filenames of generated Source Maps. + + +### Qualities + +`bundled code` - You see all generated code as a big blob of code. You don't see modules separated from each other. + +`generated code` - You see each module separated from each other, annotated with module names. You see the code generated by webpack. Example: Instead of `import {test} from "module"; test();` you see something like `var module__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); module__WEBPACK_IMPORTED_MODULE_1__.a();`. + +`transformed code` - You see each module separated from each other, annotated with module names. You see the code before webpack transforms it, but after Loaders transpile it. Example: Instead of `import {test} from "module"; class A extends test {}` you see something like `import {test} from "module"; var A = function(_test) { ... }(test);` + +`original source` - You see each module separated from each other, annotated with module names. You see the code before transpilation, as you authored it. This depends on Loader support. + +`without source content` - Contents for the sources are not included in the Source Maps. Browsers usually try to load the source from the webserver or filesystem. You have to make sure to set [`output.devtoolModuleFilenameTemplate`](/configuration/output/#output-devtoolmodulefilenametemplate) correctly to match source urls. + +`(lines only)` - Source Maps are simplified to a single mapping per line. This usually means a single mapping per statement (assuming you author is this way). This prevents you from debugging execution on statement level and from settings breakpoints on columns of a line. Combining with minimizing is not possible as minimizers usually only emit a single line. + + +### Development + +The following options are ideal for development: + +`eval` - Each module is executed with `eval()` and `//@ sourceURL`. This is pretty fast. The main disadvantage is that it doesn't display line numbers correctly since it gets mapped to transpiled code instead of the original code (No Source Maps from Loaders). + +`eval-source-map` - Each module is executed with `eval()` and a SourceMap is added as a DataUrl to the `eval()`. Initially it is slow, but it provides fast rebuild speed and yields real files. Line numbers are correctly mapped since it gets mapped to the original code. It yields the best quality SourceMaps for development. + +`cheap-eval-source-map` - Similar to `eval-source-map`, each module is executed with `eval()`. It is "cheap" because it doesn't have column mappings, it only maps line numbers. It ignores SourceMaps from Loaders and only display transpiled code similar to the `eval` devtool. + +`cheap-module-eval-source-map` - Similar to `cheap-eval-source-map`, however, in this case Source Maps from Loaders are processed for better results. However Loader Source Maps are simplified to a single mapping per line. + +### Special cases + +The following options are not ideal for development nor production. They are needed for some special cases, i. e. for some 3rd party tools. + +`inline-source-map` - A SourceMap is added as a DataUrl to the bundle. + +`cheap-source-map` - A SourceMap without column-mappings ignoring loader Source Maps. + +`inline-cheap-source-map` - Similar to `cheap-source-map` but SourceMap is added as a DataUrl to the bundle. + +`cheap-module-source-map` - A SourceMap without column-mappings that simplifies loader Source Maps to a single mapping per line. + +`inline-cheap-module-source-map` - Similar to `cheap-module-source-map` but SourceMap is added as a DataUrl to the bundle. + + +### Production + +These options are typically used in production: + +`(none)` (Omit the `devtool` option) - No SourceMap is emitted. This is a good option to start with. + +`source-map` - A full SourceMap is emitted as a separate file. It adds a reference comment to the bundle so development tools know where to find it. + +W> You should configure your server to disallow access to the Source Map file for normal users! + +`hidden-source-map` - Same as `source-map`, but doesn't add a reference comment to the bundle. Useful if you only want SourceMaps to map error stack traces from error reports, but don't want to expose your SourceMap for the browser development tools. + +W> You should not deploy the Source Map file to the webserver. Instead only use it for error report tooling. + +`nosources-source-map` - A SourceMap is created without the `sourcesContent` in it. It can be used to map stack traces on the client without exposing all of the source code. You can deploy the Source Map file to the webserver. + +W> It still exposes filenames and structure for decompiling, but it doesn't expose the original code. + +T> When using the `terser-webpack-plugin` you must provide the `sourceMap: true` option to enable SourceMap support. + + +# Target + +webpack can compile for multiple environments or _targets_. To understand what a `target` is in detail, read through [the targets concept page](/concepts/targets/). + +## `target` + +`string | function (compiler)` + +Instructs webpack to target a specific environment. + + +### `string` + +The following string values are supported via [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js): + +Option | Description +--------------------- | ----------------------- +`async-node` | Compile for usage in a Node.js-like environment (uses `fs` and `vm` to load chunks asynchronously) +`electron-main` | Compile for [Electron](https://electronjs.org/) for main process. +`electron-renderer` | Compile for [Electron](https://electronjs.org/) for renderer process, providing a target using `JsonpTemplatePlugin`, `FunctionModulePlugin` for browser environments and `NodeTargetPlugin` and `ExternalsPlugin` for CommonJS and Electron built-in modules. +`node` | Compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks) +`node-webkit` | Compile for usage in WebKit and uses JSONP for chunk loading. Allows importing of built-in Node.js modules and [`nw.gui`](http://docs.nwjs.io/en/latest/) (experimental) +`web` | Compile for usage in a browser-like environment __(default)__ +`webworker` | Compile as WebWorker + +For example, when the `target` is set to `"electron-main"`, webpack includes multiple electron specific variables. For more information on which templates and externals are used, you can refer to webpack's [source code](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js#L148-L183). + + +### `function` + +If a function is passed, then it will be called with the compiler as a parameter. Set it to a function if none of the predefined targets from the list above meet your needs. + +For example, if you don't want any of the plugins they applied: + +```js +const options = { + target: () => undefined +}; +``` + +Or you can apply specific plugins you want: + +```js +const webpack = require('webpack'); + +const options = { + target: (compiler) => { + compiler.apply( + new webpack.JsonpTemplatePlugin(options.output), + new webpack.LoaderTargetPlugin('web') + ); + } +}; +``` + + +# Watch and WatchOptions + +webpack can watch files and recompile whenever they change. This page explains how to enable this and a couple of tweaks you can make if watching does not work properly for you. + + +## `watch` + +`boolean` + +Turn on watch mode. This means that after the initial build, webpack will continue to watch for changes in any of the resolved files. Watch mode is turned off by default: + +```js +module.exports = { + //... + watch: false +}; +``` + +T> In webpack-dev-server and webpack-dev-middleware watch mode is enabled by default. + + +## `watchOptions` + +`object` + +A set of options used to customize watch mode: + +```js +module.exports = { + //... + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + } +}; +``` + + +## `watchOptions.aggregateTimeout` + +`number` + +Add a delay before rebuilding once the first file changed. This allows webpack to aggregate any other changes made during this time period into one rebuild. Pass a value in milliseconds: + +```js +module.exports = { + //... + watchOptions: { + aggregateTimeout: 300 // The default + } +}; +``` + + +## `watchOptions.ignored` + +For some systems, watching many file systems can result in a lot of CPU or memory usage. It is possible to exclude a huge folder like `node_modules`: + +```js +module.exports = { + //... + watchOptions: { + ignored: /node_modules/ + } +}; +``` + +It is also possible to have and use multiple [anymatch](https://github.com/micromatch/anymatch) patterns: + +```js +module.exports = { + //... + watchOptions: { + ignored: ['files/**/*.js', 'node_modules'] + } +}; +``` + +T> If you use `require.context`, webpack will watch your entire directory. You will need to ignore files and/or directories so that unwanted changes will not trigger a rebuild. + + +## `watchOptions.poll` + +`boolean` `number` + +Turn on [polling](https://whatis.techtarget.com/definition/polling) by passing `true`, or specifying a poll interval in milliseconds: + +```js +module.exports = { + //... + watchOptions: { + poll: 1000 // Check for changes every second + } +}; +``` + +T> If watching does not work for you, try out this option. Watching does not work with NFS and machines in VirtualBox. + + +## `info-verbosity` + +`string`: `none` `info` `verbose` + +Controls verbosity of the lifecycle messaging, e.g. the `Started watching files...` log. Setting `info-verbosity` to `verbose` will also message to console at the beginning and the end of incremental build. `info-verbosity` is set to `info` by default. + +```bash +webpack --watch --info-verbosity verbose +``` + + +## Troubleshooting + +If you are experiencing any issues, please see the following notes. There are a variety of reasons why webpack might miss a file change. + +### Changes Seen But Not Processed + +Verify that webpack is not being notified of changes by running webpack with the --progress flag. If progress shows on save but no files are outputted, it is likely a configuration issue, not a file watching issue. + +```bash +webpack --watch --progress +``` + +### Not Enough Watchers + +Verify that you have enough available watchers in your system. If this value is too low, the file watcher in Webpack won't recognize the changes: + +```bash +cat /proc/sys/fs/inotify/max_user_watches +``` + +Arch users, add `fs.inotify.max_user_watches=524288` to `/etc/sysctl.d/99-sysctl.conf` and then execute `sysctl --system`. Ubuntu users (and possibly others), execute: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`. + +### macOS fsevents Bug + +On macOS, folders can get corrupted in certain scenarios. See [this article](https://github.com/livereload/livereload-site/blob/master/livereload.com/_articles/troubleshooting/os-x-fsevents-bug-may-prevent-monitoring-of-certain-folders.md). + +### Windows Paths + +Because webpack expects absolute paths for many config options such as `__dirname + "/app/folder"` the Windows `\` path separator can break some functionality. + +Use the correct separators. I.e. `path.resolve(__dirname, "app/folder")` or `path.join(__dirname, "app", "folder")`. + +### Vim + +On some machines Vim is preconfigured with the [backupcopy option](http://vimdoc.sourceforge.net/htmldoc/options.html#'backupcopy') set to `auto`. This could potentially cause problems with the system's file watching mechanism. Switching this option to `yes` will make sure a copy of the file is made and the original one overwritten on save. + +`:set backupcopy=yes` + +### Saving in WebStorm + +When using the JetBrains WebStorm IDE, you may find that saving changed files does not trigger the watcher as you might expect. Try disabling the `safe write` option in the settings, which determines whether files are saved to a temporary location first before the originals are overwritten: uncheck `File > Settings... > System Settings > Use "safe write" (save changes to a temporary file first)`. + + +# Externals + +The `externals` configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment. This feature is typically most useful to __library developers__, however there are a variety of applications for it. + +T> __consumer__ here is any end user application that includes the library that you have bundled using webpack. + + +## `externals` + +`string` `object` `function` `regex` + +__Prevent bundling__ of certain `import`ed packages and instead retrieve these _external dependencies_ at runtime. + +For example, to include [jQuery](https://jquery.com/) from a CDN instead of bundling it: + +__index.html__ + +``` html +<script + src="https://code.jquery.com/jquery-3.1.0.js" + integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" + crossorigin="anonymous"> +</script> +``` + +__webpack.config.js__ + +```javascript +module.exports = { + //... + externals: { + jquery: 'jQuery' + } +}; +``` + +This leaves any dependent modules unchanged, i.e. the code shown below will still work: + +```javascript +import $ from 'jquery'; + +$('.my-element').animate(/* ... */); +``` + +The bundle with external dependencies can be used in various module contexts, such as [CommonJS, AMD, global and ES2015 modules](/concepts/modules). The external library may be available in any of these forms: + +- __root__: The library should be available as a global variable (e.g. via a script tag). +- __commonjs__: The library should be available as a CommonJS module. +- __commonjs2__: Similar to the above but where the export is `module.exports.default`. +- __amd__: Similar to `commonjs` but using AMD module system. + +The following syntaxes are accepted... + + +### string + +See the example above. The property name `jquery` indicates that the module `jquery` in `import $ from 'jquery'` should be excluded. In order to replace this module, the value `jQuery` will be used to retrieve a global `jQuery` variable. In other words, when a string is provided it will be treated as `root` (defined above and below). + + +### array + +```javascript +module.exports = { + //... + externals: { + subtract: ['./math', 'subtract'] + } +}; +``` + +`subtract: ['./math', 'subtract']` converts to a parent child construct, where `./math` is the parent module and your bundle only requires the subset under `subtract` variable. + + +### object + +W> An object with `{ root, amd, commonjs, ... }` is only allowed for [`libraryTarget: 'umd'`](/configuration/output/#output-librarytarget). It's not allowed for other library targets. + +```javascript +module.exports = { + //... + externals : { + react: 'react' + }, + + // or + + externals : { + lodash : { + commonjs: 'lodash', + amd: 'lodash', + root: '_' // indicates global variable + } + }, + + // or + + externals : { + subtract : { + root: ['math', 'subtract'] + } + } +}; +``` + +This syntax is used to describe all the possible ways that an external library can be available. `lodash` here is available as `lodash` under AMD and CommonJS module systems but available as `_` in a global variable form. `subtract` here is available via the property `subtract` under the global `math` object (e.g. `window['math']['subtract']`). + + +### function + +It might be useful to define your own function to control the behavior of what you want to externalize from webpack. [webpack-node-externals](https://www.npmjs.com/package/webpack-node-externals), for example, excludes all modules from the `node_modules` directory and provides some options to, for example, whitelist packages. + +It basically comes down to this: + +```javascript +module.exports = { + //... + externals: [ + function(context, request, callback) { + if (/^yourregex$/.test(request)){ + return callback(null, 'commonjs ' + request); + } + callback(); + } + ] +}; +``` + +The `'commonjs ' + request` defines the type of module that needs to be externalized. + + +### regex + +Every dependency that matches the given regular expression will be excluded from the output bundles. + +```javascript +module.exports = { + //... + externals: /^(jquery|\$)$/i +}; +``` + +In this case any dependency named `jQuery`, capitalized or not, or `$` would be externalized. + +### Combining syntaxes + +Sometimes you may want to use a combination of the above syntaxes. This can be done in the following manner: + +```javascript +module.exports = { + //... + externals: [ + { + // String + react: 'react', + // Object + lodash : { + commonjs: 'lodash', + amd: 'lodash', + root: '_' // indicates global variable + }, + // Array + subtract: ['./math', 'subtract'] + }, + // Function + function(context, request, callback) { + if (/^yourregex$/.test(request)){ + return callback(null, 'commonjs ' + request); + } + callback(); + }, + // Regex + /^(jquery|\$)$/i + ] +}; +``` + +For more information on how to use this configuration, please refer to the article on [how to author a library](/guides/author-libraries). + + +# Node + +These options configure whether to polyfill or mock certain [Node.js globals](https://nodejs.org/docs/latest/api/globals.html) and modules. This allows code originally written for the Node.js environment to run in other environments like the browser. + +This feature is provided by webpack's internal [`NodeStuffPlugin`](https://github.com/webpack/webpack/blob/master/lib/NodeStuffPlugin.js) plugin. If the target is "web" (default) or "webworker", the [`NodeSourcePlugin`](https://github.com/webpack/webpack/blob/master/lib/node/NodeSourcePlugin.js) plugin is also activated. + + +## `node` + +`object` + +This is an object where each property is the name of a Node global or module and each value may be one of the following... + +- `true`: Provide a polyfill. +- `"mock"`: Provide a mock that implements the expected interface but has little or no functionality. +- `"empty"`: Provide an empty object. +- `false`: Provide nothing. Code that expects this object may crash with a `ReferenceError`. Code that attempts to import the module using `require('modulename')` may trigger a `Cannot find module "modulename"` error. + +W> Not every Node global supports all four options. The compiler will throw an error for property-value combinations that aren't supported (e.g. `process: 'empty'`). See the sections below for more details. + +These are the defaults: + +```js +module.exports = { + //... + node: { + console: false, + global: true, + process: true, + __filename: 'mock', + __dirname: 'mock', + Buffer: true, + setImmediate: true + + // See "Other node core libraries" for additional options. + } +}; +``` + +Since webpack 3.0.0, the `node` option may be set to `false` to completely turn off the `NodeStuffPlugin` and `NodeSourcePlugin` plugins. + + +## `node.console` + +`boolean | "mock"` + +Default: `false` + +The browser provides a `console` object with a very similar interface to the Node.js `console`, so a polyfill is generally not needed. + + +## `node.process` + +`boolean | "mock"` + +Default: `true` + + +## `node.global` + +`boolean` + +Default: `true` + +See [the source](https://github.com/webpack/webpack/blob/master/buildin/global.js) for the exact behavior of this object. + + +## `node.__filename` + +`boolean | "mock"` + +Default: `"mock"` + +Options: + +- `true`: The filename of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). +- `false`: The regular Node.js `__filename` behavior. The filename of the __output__ file when run in a Node.js environment. +- `"mock"`: The fixed value `"index.js"`. + + +## `node.__dirname` + +`boolean | "mock"` + +Default: `"mock"` + +Options: + +- `true`: The dirname of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). +- `false`: The regular Node.js `__dirname` behavior. The dirname of the __output__ file when run in a Node.js environment. +- `"mock"`: The fixed value `"/"`. + + +## `node.Buffer` + +`boolean | "mock"` + +Default: `true` + + +## `node.setImmediate` + +`boolean | "mock" | "empty"` + +Default: `true` + + +## Other node core libraries + +`boolean | "mock" | "empty"` + +W> This option is only activated (via `NodeSourcePlugin`) when the target is unspecified, "web" or "webworker". + +Polyfills for Node.js core libraries from [`node-libs-browser`](https://github.com/webpack/node-libs-browser) are used if available, when the `NodeSourcePlugin` plugin is enabled. See the list of [Node.js core libraries and their polyfills](https://github.com/webpack/node-libs-browser#readme). + +By default, webpack will polyfill each library if there is a known polyfill or do nothing if there is not one. In the latter case, webpack will behave as if the module name was configured with the `false` value. + +T> To import a built-in module, use [`__non_webpack_require__`](/api/module-variables/#__non_webpack_require__-webpack-specific-), i.e. `__non_webpack_require__('modulename')` instead of `require('modulename')`. + +Example: + +```js +module.exports = { + //... + node: { + dns: 'mock', + fs: 'empty', + path: true, + url: false + } +}; +``` + + +# Performance + +These options allows you to control how webpack notifies you of assets and entry points that exceed a specific file limit. +This feature was inspired by the idea of [webpack Performance Budgets](https://github.com/webpack/webpack/issues/3216). + +## `performance` + +`object` + +Configure how performance hints are shown. For example if you have an asset that is over 250kb, webpack will emit a warning notifying you of this. + + +## `performance.hints` + +`false | "error" | "warning"` + +Turns hints on/off. In addition, tells webpack to throw either an error or a warning when hints are found. This property is set to `"warning"` by default. + +Given an asset is created that is over 250kb: + +```js +module.exports = { + //... + performance: { + hints: false + } +}; +``` + +No hint warnings or errors are shown. + +```js +module.exports = { + //... + performance: { + hints: 'warning' + } +}; +``` + +A warning will be displayed notifying you of a large asset. We recommend something like this for development environments. + +```js +module.exports = { + //... + performance: { + hints: 'error' + } +}; +``` + +An error will be displayed notifying you of a large asset. We recommend using `hints: "error"` during production builds to help prevent deploying production bundles that are too large, impacting webpage performance. + +## `performance.maxEntrypointSize` + +`int` + +An entry point represents all assets that would be utilized during initial load time for a specific entry. This option controls when webpack should emit performance hints based on the maximum entry point size. The default value is `250000` (bytes). + +```js +module.exports = { + //... + performance: { + maxEntrypointSize: 400000 + } +}; +``` + +## `performance.maxAssetSize` + +`int` + +An asset is any emitted file from webpack. This option controls when webpack emits a performance hint based on individual asset size. The default value is `250000` (bytes). + + +```js +module.exports = { + //... + performance: { + maxAssetSize: 100000 + } +}; +``` + +## `performance.assetFilter` + +`Function` + +This property allows webpack to control what files are used to calculate performance hints. The default function is seen below: + +```js +function assetFilter(assetFilename) { + return !(/\.map$/.test(assetFilename)); +} +``` + +You can override this property by passing your own function in: + +```js +module.exports = { + //... + performance: { + assetFilter: function(assetFilename) { + return assetFilename.endsWith('.js'); + } + } +}; +``` + +The example above will only give you performance hints based on `.js` files. + + +# Stats + +The `stats` option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you don't want to use `quiet` or `noInfo` because you want some bundle information, but not all of it. + +T> For webpack-dev-server, this property needs to be in the `devServer` object. + +W> This option does not have any effect when using the Node.js API. + +## `stats` + +`object` `string` + +There are some presets available to use as a shortcut. Use them like this: + +```js +module.exports = { + //... + stats: 'errors-only' +}; +``` + +| Preset | Alternative | Description | +|--------|-------------|-------------| +| `"errors-only"` | _none_ | Only output when errors happen | +| `"minimal"` | _none_ | Only output when errors or new compilation happen | +| `"none"` | `false` | Output nothing | +| `"normal"` | `true` | Standard output | +| `"verbose"` | _none_ | Output everything | + +For more granular control, it is possible to specify exactly what information you want. Please note that all of the options in this object are optional. + +<!-- eslint-skip --> + +```js +module.exports = { + //... + stats: { + // fallback value for stats options when an option is not defined (has precedence over local webpack defaults) + all: undefined, + + // Add asset Information + assets: true, + + // Sort assets by a field + // You can reverse the sort with `!field`. + // Some possible values: 'id' (default), 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + assetsSort: "field", + + // Add build date and time information + builtAt: true, + + // Add information about cached (not built) modules + cached: true, + + // Show cached assets (setting this to `false` only shows emitted files) + cachedAssets: true, + + // Add children information + children: true, + + // Add chunk information (setting this to `false` allows for a less verbose output) + chunks: true, + + // Add namedChunkGroups information + chunkGroups: true, + + // Add built modules information to chunk information + chunkModules: true, + + // Add the origins of chunks and chunk merging info + chunkOrigins: true, + + // Sort the chunks by a field + // You can reverse the sort with `!field`. Default is `id`. + // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + chunksSort: "field", + + // Context directory for request shortening + context: "../src/", + + // `webpack --colors` equivalent + colors: false, + + // Display the distance from the entry point for each module + depth: false, + + // Display the entry points with the corresponding bundles + entrypoints: false, + + // Add --env information + env: false, + + // Add errors + errors: true, + + // Add details to errors (like resolving log) + errorDetails: true, + + // Exclude assets from being displayed in stats + // This can be done with a String, a RegExp, a Function getting the assets name + // and returning a boolean or an Array of the above. + excludeAssets: "filter" | /filter/ | (assetName) => true | false | + ["filter"] | [/filter/] | [(assetName) => true|false], + + // Exclude modules from being displayed in stats + // This can be done with a String, a RegExp, a Function getting the modules source + // and returning a boolean or an Array of the above. + excludeModules: "filter" | /filter/ | (moduleSource) => true | false | + ["filter"] | [/filter/] | [(moduleSource) => true|false], + + // See excludeModules + exclude: "filter" | /filter/ | (moduleSource) => true | false | + ["filter"] | [/filter/] | [(moduleSource) => true|false], + + // Add the hash of the compilation + hash: true, + + // Set the maximum number of modules to be shown + maxModules: 15, + + // Add built modules information + modules: true, + + // Sort the modules by a field + // You can reverse the sort with `!field`. Default is `id`. + // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + modulesSort: "field", + + // Show dependencies and origin of warnings/errors (since webpack 2.5.0) + moduleTrace: true, + + // Show performance hint when file size exceeds `performance.maxAssetSize` + performance: true, + + // Show the exports of the modules + providedExports: false, + + // Add public path information + publicPath: true, + + // Add information about the reasons why modules are included + reasons: true, + + // Add the source code of modules + source: false, + + // Add timing information + timings: true, + + // Show which exports of a module are used + usedExports: false, + + // Add webpack version information + version: true, + + // Add warnings + warnings: true, + + // Filter warnings to be shown (since webpack 2.4.0), + // can be a String, Regexp, a function getting the warning and returning a boolean + // or an Array of a combination of the above. First match wins. + warningsFilter: "filter" | /filter/ | ["filter", /filter/] | (warning) => true|false + } +} +``` + +If you want to use one of the pre-defined behaviours e.g. `'minimal'` but still override one or more of the rules, see [the source code](https://github.com/webpack/webpack/blob/master/lib/Stats.js#L1394-L1401). You would want to copy the configuration options from `case 'minimal': ...` and add your additional rules while providing an object to `stats`. + +__webpack.config.js__ + +```javascript +module.exports = { + //.. + stats: { + // copied from `'minimal'` + all: false, + modules: true, + maxModules: 0, + errors: true, + warnings: true, + // our additional options + moduleTrace: true, + errorDetails: true + } +}; +``` + +### Sorting fields + +For `assetsSort`, `chunksSort` and `moduleSort` there are several possible fields that you can sort items by: + +- `id` is the item's id; +- `name` - a item's name that was assigned to it upon importing; +- `size` - a size of item in bytes; +- `chunks` - what chunks the item originates from (for example, if there are multiple subchunks for one chunk - the subchunks will be grouped together according to their main chunk); +- `errors` - amount of errors in items; +- `warnings` - amount of warnings in items; +- `failed` - whether the item has failed compilation; +- `cacheable` - whether the item is cacheable; +- `built` - whether the asset has been built; +- `prefetched` - whether the asset will be prefetched; +- `optional` - whether the asset is optional; +- `identifier` - identifier of the item; +- `index` - item's processing index; +- `index2` +- `profile` +- `issuer` - an identifier of the issuer; +- `issuerId` - an id of the issuer; +- `issuerName` - a name of the issuer; +- `issuerPath` - a full issuer object. There's no real need to sort by this field; + + +# Other Options + + +These are the remaining configuration options supported by webpack. + +W> Help Wanted: This page is still a work in progress. If you are familiar with any of the options for which the description or examples are incomplete, please create an issue and submit a PR at the [docs repo](https://github.com/webpack/webpack.js.org)! + + +## `amd` + +`object` + +Set the value of `require.amd` or `define.amd`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + amd: { + jQuery: true + } +}; +``` + +Certain popular modules written for AMD, most notably jQuery versions 1.7.0 to 1.9.1, will only register as an AMD module if the loader indicates it has taken [special allowances](https://github.com/amdjs/amdjs-api/wiki/jQuery-and-AMD) for multiple versions being included on a page. + +The allowances were the ability to restrict registrations to a specific version or to support different sandboxes with different defined modules. + +This option allows you to set the key your module looks for to a truthy value. +As it happens, the AMD support in webpack ignores the defined name anyways. + + +## `bail` + +`boolean` + +Fail out on the first error instead of tolerating it. By default webpack will log these errors in red in the terminal, as well as the browser console when using HMR, but continue bundling. To enable it: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + bail: true +}; +``` + +This will force webpack to exit its bundling process. + + +## `cache` + +`boolean` `object` + +Cache the generated webpack modules and chunks to improve build speed. Caching is enabled by default while in watch mode. To disable caching simply pass: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + cache: false +}; +``` + +If an object is passed, webpack will use this object for caching. Keeping a reference to this object will allow one to share the same cache between compiler calls: + +__webpack.config.js__ + +```javascript +let SharedCache = {}; + +module.exports = { + //... + cache: SharedCache +}; +``` + +W> Don't share the cache between calls with different options. + +?> Elaborate on the warning and example - calls with different configuration options? + + +## `loader` + +`object` + +Expose custom values into the loader context. + +?> Add an example... + + +## `parallelism` + +`number` + +Limit the number of parallel processed modules. Can be used to fine tune performance or to get more reliable profiling results. + + +## `profile` + +`boolean` + +Capture a "profile" of the application, including statistics and hints, which can then be dissected using the [Analyze](https://webpack.github.io/analyse/) tool. + +T> Use the [StatsPlugin](https://www.npmjs.com/package/stats-webpack-plugin) for more control over the generated profile. + +T> Combine with `parallelism: 1` for better results. + + +## `recordsPath` + +`string` + +Use this option to generate a JSON file containing webpack "records" -- pieces of data used to store module identifiers across multiple builds. You can use this file to track how modules change between builds. To generate one, simply specify a location: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + recordsPath: path.join(__dirname, 'records.json') +}; +``` + +Records are particularly useful if you have a complex setup that leverages [Code Splitting](/guides/code-splitting). The data can be used to ensure the split bundles are achieving the [caching](/guides/caching) behavior you need. + +T> Note that although this file is generated by the compiler, you may still want to track it in source control to keep a history of how it has changed over time. + +W> Setting `recordsPath` will essentially set `recordsInputPath` and `recordsOutputPath` to the same location. This is usually all that's necessary unless you decide to change the name of the file containing the records. See below for an example. + + +## `recordsInputPath` + +`string` + +Specify the file from which to read the last set of records. This can be used to rename a records file. See the example below. + + +## `recordsOutputPath` + +`string` + +Specify where the records should be written. The following example shows how you might use this option in combination with `recordsInputPath` to rename a records file: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + recordsInputPath: path.join(__dirname, 'records.json'), + recordsOutputPath: path.join(__dirname, 'newRecords.json') +}; +``` + + +## `name` + +`string` + +Name of the configuration. Used when loading multiple configurations. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + name: 'admin-app' +}; +``` diff --git a/src/content/contribute/_contribute_all.md b/src/content/contribute/_contribute_all.md new file mode 100644 index 000000000000..beab316a12a7 --- /dev/null +++ b/src/content/contribute/_contribute_all.md @@ -0,0 +1,979 @@ + + +# Contribute + +The people who contribute to webpack do so for the love of open source, our users and ecosystem, and most importantly, pushing the web forward together. Because of our [Open Collective](https://opencollective.com/webpack) model for funding and transparency, we are able to funnel support and funds through contributors, dependent projects, and the contributor and core teams. To make a donation, simply click the button below... + +<div align="center"> + <a href="https://opencollective.com/webpack/donate" target="_blank"> + <img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" width=300 /> + </a> +</div> + +But what is the return on the investment? + + +## Developers + +The biggest core feature we'd like to provide is enjoyable development experience. Developers like you can help by contributing to rich and vibrant documentation, issuing pull requests to help us cover niche use cases, and to help sustain what you love about webpack. + +### How Can I Help? + +Anybody can help by doing any of the following: + +- Ask your employer to use webpack in projects. +- Help us write and maintain the content on this site (see the [writer's guide](/writers-guide)). +- Contribute to the [core repository](https://github.com/webpack/webpack). +- Become a backer or sponsor on [open collective](https://opencollective.com/webpack#support). + +### Encouraging Employers + +You can ask your employer to improve your workflow by leveraging webpack: an all-in-one tool for fonts, images and image optimization, and json. Explain to them how webpack will attempt to bundle your code and assets the best it can for the smallest file size, leading to speedier sites and applications. + +### Your Contributions + +Contributing to webpack is not contributing to an exclusive club. You as a developer are contributing to the overall health of downstream projects. Hundreds, if not thousands, of projects depend on webpack and contributing will make the ecosystem better for all users. + +The remainder of this section of the site is dedicated to developers such as yourself who would like to become a part of our ever-growing community: + +- [Writing a Loader](./writing-a-loader) +- [Writing a Plugin](./writing-a-plugin) +- [Plugin Patterns](./plugin-patterns) +- [Release Process](./release-process) + + +## Executives + +CTO's, VPs, and owners can help too! + +<!-- add slides here regarding monetary value/dev time/tooling --> + +webpack is an all-in-one tool for bundling your code. It can handle fonts, images, data and more with the help of community-driven plugins and loaders. Having all of your assets be handled by one tool is immensely helpful, as you or your team can spend less time making sure a machine with many moving parts is working correctly and more time building your product. + +### Sponsorship + +Aside from monetary assistance, companies can support webpack by: + +- Providing developers that are not actively working on a project. +- Contributing computing power for improved CI and regression testing. + +You can also encourage your developers to contribute to the ecosystem by open-sourcing webpack loaders, plugins and other utilities. And, as mentioned above, we would greatly appreciate any help increasing our CI/CD infrastructure. + +### Anyone Else + +To anyone else who is interested in helping our mission -- e.g. venture capitalists, government entities, digital agencies, etc. -- we would love for you to work with us, one of the top npm packages, to improve your product! Please don't hesitate to reach out with questions. + +<!-- add slides here --> + + +# Writer's Guide + +The following sections contain all you need to know about editing and formatting the content within this site. Make sure to do some research before starting your edits or additions. Sometimes the toughest part is finding where the content should live and determining whether or not it already exists. + + +## Process + +1. Check related issue if an article links to one. +2. Hit `edit` and expand on the structure. +3. PR changes. + + +## YAML Frontmatter + +Each article contains a small section at the top written in [YAML Frontmatter](https://jekyllrb.com/docs/frontmatter/): + +``` yaml +--- +title: My Article +group: My Sub-Section +sort: 3 +contributors: + - [github username] +related: + - title: Title of Related Article + url: [url of related article] +--- +``` + +Let's break these down: + +- `title`: The name of the article. +- `group`: The name of the sub-section +- `sort`: The order of the article within its section (or) sub-section if it is present. +- `contributors`: A list of GitHub usernames who have contributed to this article. +- `related`: Any related reading or useful examples. + +Note that `related` will generate a __Further Reading__ section at the bottom of the page and `contributors` will yield a __Contributors__ section below it. If you edit an article and would like recognition, don't hesitate to add your GitHub username to the `contributors` list. + + +## Article Structure + +1. Brief Introduction - a paragraph or two so you get the basic idea about the what and why. +2. Outline Remaining Content – how the content will be presented. +3. Main Content - tell what you promised to tell. +4. Conclusion - tell what you told and recap the main points. + + +## Typesetting + +- webpack should always be written in lower-case letters. Even at the beginning of a sentence. ([source](https://github.com/webpack/media#name)) +- loaders are enclosed in backticks and [kebab-cased](https://en.wikipedia.org/w/index.php?title=Kebab_case): `css-loader`, `ts-loader`, … +- plugins are enclosed in backticks and [camel-cased](https://en.wikipedia.org/wiki/Camel_case): `BannerPlugin`, `NpmInstallWebpackPlugin`, … +- Use "webpack 2" to refer to a specific webpack version (~~"webpack v2"~~) +- Use ES5; ES2015, ES2016, … to refer to the ECMAScript standards (~~ES6~~, ~~ES7~~) + + +## Formatting + +### Code + +__Syntax: \`\`\`javascript … \`\`\`__ + +```javascript +function foo () { + return 'bar'; +} + +foo(); +``` + +### Lists + +- Boo +- Foo +- Zoo + +Lists should be ordered alphabetically. + +### Tables + +Parameter | Explanation | Input Type | Default Value +----------- | ------------------------------------------------ | ---------- |-------------- +--debug | Switch loaders to debug mode | boolean | false +--devtool | Define source map type for the bundled resources | string | - +--progress | Print compilation progress in percentage | boolean | false + +Tables should also be ordered alphabetically. + +### Configuration Properties + +The [configuration](/configuration) properties should be ordered alphabetically as well: + +- `devServer.compress` +- `devServer.contentBase` +- `devServer.hot` + +### Quotes + +#### Blockquote + +__Syntax: \>__ + +> This is a blockquote. + +#### Tip + +__Syntax: T\>__ + +T> This is a tip. + +__Syntax: W\>__ + +W> This is a warning. + +__Syntax: ?\>__ + +?> This is a todo. + + +# Writing a Loader + +A loader is a node module that exports a function. This function is called when a resource should be transformed by this loader. The given function will have access to the [Loader API](/api/loaders/) using the `this` context provided to it. + + +## Setup + +Before we dig into the different types of loaders, their usage, and examples, let's take a look at the three ways you can develop and test a loader locally. + +To test a single loader, you can simply use `path` to `resolve` a local file within a rule object: + +__webpack.config.js__ + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + use: [ + { + loader: path.resolve('path/to/loader.js'), + options: {/* ... */} + } + ] + } + ] + } +}; +``` + +To test multiple, you can utilize the `resolveLoader.modules` configuration to update where webpack will search for loaders. For example, if you had a local `/loaders` directory in your project: + +__webpack.config.js__ + +```js +module.exports = { + //... + resolveLoader: { + modules: [ + 'node_modules', + path.resolve(__dirname, 'loaders') + ] + } +}; +``` + +Last but not least, if you've already created a separate repository and package for your loader, you could [`npm link`](https://docs.npmjs.com/cli/link) it to the project in which you'd like to test it out. + + +## Simple Usage + +When a single loader is applied to the resource, the loader is called with only one parameter -- a string containing the content of the resource file. + +Synchronous loaders can simply `return` a single value representing the transformed module. In more complex cases, the loader can return any number of values by using the `this.callback(err, values...)` function. Errors are either passed to the `this.callback` function or thrown in a sync loader. + +The loader is expected to give back one or two values. The first value is a resulting JavaScript code as string or buffer. The second optional value is a SourceMap as JavaScript object. + + +## Complex Usage + +When multiple loaders are chained, it is important to remember that they are executed in reverse order -- either right to left or bottom to top depending on array format. + +- The last loader, called first, will be passed the contents of the raw resource. +- The first loader, called last, is expected to return JavaScript and an optional source map. +- The loaders in between will be executed with the result(s) of the previous loader in the chain. + +So, in the following example, the `foo-loader` would be passed the raw resource and the `bar-loader` would receive the output of the `foo-loader` and return the final transformed module and a source map if necessary. + +__webpack.config.js__ + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js/, + use: [ + 'bar-loader', + 'foo-loader' + ] + } + ] + } +}; +``` + + +## Guidelines + +The following guidelines should be followed when writing a loader. They are ordered in terms of importance and some only apply in certain scenarios, read the detailed sections that follow for more information. + +- Keep them __simple__. +- Utilize __chaining__. +- Emit __modular__ output. +- Make sure they're __stateless__. +- Employ __loader utilities__. +- Mark __loader dependencies__. +- Resolve __module dependencies__. +- Extract __common code__. +- Avoid __absolute paths__. +- Use __peer dependencies__. + +### Simple + +Loaders should do only a single task. This not only makes the job of maintaining each loader easier, but also allows them to be chained for usage in more scenarios. + +### Chaining + +Take advantage of the fact that loaders can be chained together. Instead of writing a single loader that tackles five tasks, write five simpler loaders that divide this effort. Isolating them not only keeps each individual loader simple, but may allow for them to be used for something you hadn't thought of originally. + +Take the case of rendering a template file with data specified via loader options or query parameters. It could be written as a single loader that compiles the template from source, executes it and returns a module that exports a string containing the HTML code. However, in accordance with guidelines, a simple `apply-loader` exists that can be chained with other open source loaders: + +- `jade-loader`: Convert template to a module that exports a function. +- `apply-loader`: Executes the function with loader options and returns raw HTML. +- `html-loader`: Accepts HTML and outputs a valid JavaScript module. + +T> The fact that loaders can be chained also means they don't necessarily have to output JavaScript. As long as the next loader in the chain can handle its output, the loader can return any type of module. + +### Modular + +Keep the output modular. Loader generated modules should respect the same design principles as normal modules. + +### Stateless + +Make sure the loader does not retain state between module transformations. Each run should always be independent of other compiled modules as well as previous compilations of the same module. + +### Loader Utilities + +Take advantage of the [`loader-utils`](https://github.com/webpack/loader-utils) package. It provides a variety of useful tools but one of the most common is retrieving the options passed to the loader. Along with `loader-utils`, the [`schema-utils`](https://github.com/webpack-contrib/schema-utils) package should be used for consistent JSON Schema based validation of loader options. Here's a brief example that utilizes both: + +__loader.js__ + +```js +import { getOptions } from 'loader-utils'; +import validateOptions from 'schema-utils'; + +const schema = { + type: 'object', + properties: { + test: { + type: 'string' + } + } +}; + +export default function(source) { + const options = getOptions(this); + + validateOptions(schema, options, 'Example Loader'); + + // Apply some transformations to the source... + + return `export default ${ JSON.stringify(source) }`; +} +``` + +### Loader Dependencies + +If a loader uses external resources (i.e. by reading from filesystem), they __must__ indicate it. This information is used to invalidate cacheable loaders and recompile in watch mode. Here's a brief example of how to accomplish this using the `addDependency` method: + +__loader.js__ + +```js +import path from 'path'; + +export default function(source) { + var callback = this.async(); + var headerPath = path.resolve('header.js'); + + this.addDependency(headerPath); + + fs.readFile(headerPath, 'utf-8', function(err, header) { + if(err) return callback(err); + callback(null, header + '\n' + source); + }); +} +``` + +### Module Dependencies + +Depending on the type of module, there may be a different schema used to specify dependencies. In CSS for example, the `@import` and `url(...)` statements are used. These dependencies should be resolved by the module system. + +This can be done in one of two ways: + +- By transforming them to `require` statements. +- Using the `this.resolve` function to resolve the path. + +The `css-loader` is a good example of the first approach. It transforms dependencies to `require`s, by replacing `@import` statements with a `require` to the other stylesheet and `url(...)` with a `require` to the referenced file. + +In the case of the `less-loader`, it cannot transform each `@import` to a `require` because all `.less` files must be compiled in one pass for variables and mixin tracking. Therefore, the `less-loader` extends the less compiler with custom path resolving logic. It then takes advantage of the second approach, `this.resolve`, to resolve the dependency through webpack. + +T> If the language only accepts relative urls (e.g. `url(file)` always refers to `./file`), you can use the `~` convention to specify references to installed modules (e.g. those in `node_modules`). So, in the case of `url`, that would look something like `url('~some-library/image.jpg')`. + +### Common Code + +Avoid generating common code in every module the loader processes. Instead, create a runtime file in the loader and generate a `require` to that shared module. + +### Absolute Paths + +Don't insert absolute paths into the module code as they break hashing when the root for the project is moved. There's a [`stringifyRequest`](https://github.com/webpack/loader-utils#stringifyrequest) method in `loader-utils` which can be used to convert an absolute path to a relative one. + +### Peer Dependencies + +If the loader you're working on is a simple wrapper around another package, then you should include the package as a `peerDependency`. This approach allows the application's developer to specify the exact version in the `package.json` if desired. + +For instance, the `sass-loader` [specifies `node-sass`](https://github.com/webpack-contrib/sass-loader/blob/master/package.json) as peer dependency like so: + +```json +{ + "peerDependencies": { + "node-sass": "^4.0.0" + } +} +``` + + +## Testing + +So you've written a loader, followed the guidelines above, and have it set up to run locally. What's next? Let's go through a simple unit testing example to ensure our loader is working the way we expect. We'll be using the [Jest](https://facebook.github.io/jest/) framework to do this. We'll also install `babel-jest` and some presets that will allow us to use the `import` / `export` and `async` / `await`. Let's start by installing and saving these as a `devDependencies`: + +``` bash +npm install --save-dev jest babel-jest babel-preset-env +``` + +__.babelrc__ + +```json +{ + "presets": [[ + "env", + { + "targets": { + "node": "4" + } + } + ]] +} +``` + +Our loader will process `.txt` files and simply replace any instance of `[name]` with the `name` option given to the loader. Then it will output a valid JavaScript module containing the text as it's default export: + +__src/loader.js__ + +```js +import { getOptions } from 'loader-utils'; + +export default function loader(source) { + const options = getOptions(this); + + source = source.replace(/\[name\]/g, options.name); + + return `export default ${ JSON.stringify(source) }`; +} +``` + +We'll use this loader to process the following file: + +__test/example.txt__ + +``` text +Hey [name]! +``` + +Pay close attention to this next step as we'll be using the [Node.js API](/api/node) and [`memory-fs`](https://github.com/webpack/memory-fs) to execute webpack. This lets us avoid emitting `output` to disk and will give us access to the `stats` data which we can use to grab our transformed module: + +``` bash +npm install --save-dev webpack memory-fs +``` + +__test/compiler.js__ + +```js +import path from 'path'; +import webpack from 'webpack'; +import memoryfs from 'memory-fs'; + +export default (fixture, options = {}) => { + const compiler = webpack({ + context: __dirname, + entry: `./${fixture}`, + output: { + path: path.resolve(__dirname), + filename: 'bundle.js', + }, + module: { + rules: [{ + test: /\.txt$/, + use: { + loader: path.resolve(__dirname, '../src/loader.js'), + options: { + name: 'Alice' + } + } + }] + } + }); + + compiler.outputFileSystem = new memoryfs(); + + return new Promise((resolve, reject) => { + compiler.run((err, stats) => { + if (err || stats.hasErrors()) reject(err); + + resolve(stats); + }); + }); +}; +``` + +T> In this case, we've inlined our webpack configuration but you can also accept a configuration as a parameter to the exported function. This would allow you to test multiple setups using the same compiler module. + +And now, finally, we can write our test and add an npm script to run it: + +__test/loader.test.js__ + +```js +import compiler from './compiler.js'; + +test('Inserts name and outputs JavaScript', async () => { + const stats = await compiler('example.txt'); + const output = stats.toJson().modules[0].source; + + expect(output).toBe('export default "Hey Alice!\\n"'); +}); +``` + +__package.json__ + +```json +{ + "scripts": { + "test": "jest" + } +} +``` + +With everything in place, we can run it and see if our new loader passes the test: + +``` bash + PASS test/loader.test.js + ✓ Inserts name and outputs JavaScript (229ms) + +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: 1.853s, estimated 2s +Ran all test suites. +``` + +It worked! At this point you should be ready to start developing, testing, and deploying your own loaders. We hope that you'll share your creations with the rest of the community! + + +# Writing a Plugin + +Plugins expose the full potential of the webpack engine to third-party developers. Using staged build callbacks, developers can introduce their own behaviors into the webpack build process. Building plugins is a bit more advanced than building loaders, because you'll need to understand some of the webpack low-level internals to hook into them. Be prepared to read some source code! + +## Creating a Plugin + +A plugin for webpack consists of + +- A named JavaScript function. +- Defines `apply` method in its prototype. +- Specifies an [event hook](/api/compiler-hooks/) to tap into. +- Manipulates webpack internal instance specific data. +- Invokes webpack provided callback after functionality is complete. + +```javascript +// A JavaScript class. +class MyExampleWebpackPlugin { + // Define `apply` as its prototype method which is supplied with compiler as its argument + apply(compiler) { + // Specify the event hook to attach to + compiler.hooks.emit.tapAsync( + 'MyExampleWebpackPlugin', + (compilation, callback) => { + console.log('This is an example plugin!'); + console.log('Here’s the `compilation` object which represents a single build of assets:', compilation); + + // Manipulate the build using the plugin API provided by webpack + compilation.addModule(/* ... */); + + callback(); + } + ); + } +} +``` + +## Basic plugin architecture + +Plugins are instantiated objects with an `apply` method on their prototype. This `apply` method is called once by the webpack compiler while installing the plugin. The `apply` method is given a reference to the underlying webpack compiler, which grants access to compiler callbacks. A simple plugin is structured as follows: + +```javascript +class HelloWorldPlugin { + apply(compiler) { + compiler.hooks.done.tap('Hello World Plugin', ( + stats /* stats is passed as argument when done hook is tapped. */ + ) => { + console.log('Hello World!'); + }); + } +} + +module.exports = HelloWorldPlugin; +``` + +Then to use the plugin, include an instance in your webpack config `plugins` array: + +```javascript +// webpack.config.js +var HelloWorldPlugin = require('hello-world'); + +module.exports = { + // ... config settings here ... + plugins: [new HelloWorldPlugin({ options: true })] +}; +``` + +## Compiler and Compilation + +Among the two most important resources while developing plugins are the `compiler` and `compilation` objects. Understanding their roles is an important first step in extending the webpack engine. + +```javascript +class HelloCompilationPlugin { + apply(compiler) { + // Tap into compilation hook which gives compilation as argument to the callback function + compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => { + // Now we can tap into various hooks available through compilation + compilation.hooks.optimize.tap('HelloCompilationPlugin', () => { + console.log('Assets are being optimized.'); + }); + }); + } +} + +module.exports = HelloCompilationPlugin; +``` + +The list of hooks available on the `compiler`, `compilation`, and other important objects, see the [plugins API](/api/plugins/) docs. + +## Async event hooks + +Some plugin hooks are asynchronous. To tap into them, we can use `tap` method which will behave in synchronous manner or use one of `tapAsync` method or `tapPromise` method which are asynchronous methods. + +### tapAsync + +When we use `tapAsync` method to tap into plugins, we need to call the callback function which is supplied as the last argument to our function. + +```javascript +class HelloAsyncPlugin { + apply(compiler) { + compiler.hooks.emit.tapAsync('HelloAsyncPlugin', (compilation, callback) => { + // Do something async... + setTimeout(function() { + console.log('Done with async work...'); + callback(); + }, 1000); + }); + } +} + +module.exports = HelloAsyncPlugin; +``` + +#### tapPromise + +When we use `tapPromise` method to tap into plugins, we need to return a promise which resolves when our asynchronous task is completed. + +```javascript +class HelloAsyncPlugin { + apply(compiler) { + compiler.hooks.emit.tapPromise('HelloAsyncPlugin', compilation => { + // return a Promise that resolves when we are done... + return new Promise((resolve, reject) => { + setTimeout(function() { + console.log('Done with async work...'); + resolve(); + }, 1000); + }); + }); + } +} + +module.exports = HelloAsyncPlugin; +``` + +## Example + +Once we can latch onto the webpack compiler and each individual compilations, the possibilities become endless for what we can do with the engine itself. We can reformat existing files, create derivative files, or fabricate entirely new assets. + +Let's write a simple example plugin that generates a new build file called `filelist.md`; the contents of which will list all of the asset files in our build. This plugin might look something like this: + +```javascript +class FileListPlugin { + apply(compiler) { + // emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well + compiler.hooks.emit.tapAsync('FileListPlugin', (compilation, callback) => { + // Create a header string for the generated file: + var filelist = 'In this build:\n\n'; + + // Loop through all compiled assets, + // adding a new line item for each filename. + for (var filename in compilation.assets) { + filelist += '- ' + filename + '\n'; + } + + // Insert this list into the webpack build as a new file asset: + compilation.assets['filelist.md'] = { + source: function() { + return filelist; + }, + size: function() { + return filelist.length; + } + }; + + callback(); + }); + } +} + +module.exports = FileListPlugin; +``` + +## Different Plugin Shapes + +A plugin can be classified into types based on the event hooks it taps into. Every event hook is pre-defined as synchronous or asynchronous or waterfall or parallel hook and hook is called internally using call/callAsync method. The list of hooks that are supported or can be tapped into are generally specified in this.hooks property. + +For example:- + +```javascript +this.hooks = { + shouldEmit: new SyncBailHook(['compilation']) +}; +``` + +It represents that the only hook supported is `shouldEmit` which is a hook of `SyncBailHook` type and the only parameter which will be passed to any plugin that taps into `shouldEmit` hook is `compilation`. + +Various types of hooks supported are :- + +### Synchronous Hooks + +- __SyncHook__ + + - Defined as `new SyncHook([params])` + - Tapped into using `tap` method. + - Called using `call(...params)` method. + +- __Bail Hooks__ + + - Defined using `SyncBailHook[params]` + - Tapped into using `tap` method. + - Called using `call(...params)` method. + + In these type of hooks, each of the plugin callbacks will be invoked one after the other with the specific `args`. If any value is returned except undefined by any plugin, then that value is returned by hook and no further plugin callback is invoked. Many useful events like `optimizeChunks`, `optimizeChunkModules` are SyncBailHooks. + +- __Waterfall Hooks__ + + - Defined using `SyncWaterfallHook[params]` + - Tapped into using `tap` method. + - Called using `call( ... params)` method + + Here each of the plugins are called one after the other with the arguments from the return value of the previous plugin. The plugin must take the order of its execution into account. + It must accept arguments from the previous plugin that was executed. The value for the first plugin is `init`. Hence at least 1 param must be supplied for waterfall hooks. This pattern is used in the Tapable instances which are related to the webpack templates like `ModuleTemplate`, `ChunkTemplate` etc. + +### Asynchronous Hooks + +- __Async Series Hook__ + + - Defined using `AsyncSeriesHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + The plugin handler functions are called with all arguments and a callback function with the signature `(err?: Error) -> void`. The handler functions are called in order of registration. `callback` is called after all the handlers are called. + This is also a commonly used pattern for events like `emit`, `run`. + +- __Async waterfall__ The plugins will be applied asynchronously in the waterfall manner. + + - Defined using `AsyncWaterfallHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + The plugin handler functions are called with the current value and a callback function with the signature `(err: Error, nextValue: any) -> void.` When called `nextValue` is the current value for the next handler. The current value for the first handler is `init`. After all handlers are applied, callback is called with the last value. If any handler passes a value for `err`, the callback is called with this error and no more handlers are called. + This plugin pattern is expected for events like `before-resolve` and `after-resolve`. + +- __Async Series Bail__ + + - Defined using `AsyncSeriesBailHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + someMethod() { + // Call a hook: + this.hooks.compilation.call(); + +- __Async Parallel__ + + - Defined using `AsyncParallelHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + +- __Async Series Bail__ + + - Defined using `AsyncSeriesBailHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + +# Plugin Patterns + +Plugins grant unlimited opportunity to perform customizations within the webpack build system. This allows you to create custom asset types, perform unique build modifications, or even enhance the webpack runtime while using middleware. The following are some features of webpack that become useful while writing plugins. + +## Exploring assets, chunks, modules, and dependencies + +After a compilation is sealed, all structures within the compilation may be traversed. + +```javascript +class MyPlugin { + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + // Explore each chunk (build output): + compilation.chunks.forEach(chunk => { + // Explore each module within the chunk (built inputs): + chunk.modules.forEach(module => { + // Explore each source file path that was included into the module: + module.fileDependencies.forEach(filepath => { + // we've learned a lot about the source structure now... + }); + }); + + // Explore each asset filename generated by the chunk: + chunk.files.forEach(filename => { + // Get the asset source for each file generated by the chunk: + var source = compilation.assets[filename].source(); + }); + }); + + callback(); + }); + } +} +module.exports = MyPlugin; +``` + +- `compilation.modules`: An array of modules (built inputs) in the compilation. Each module manages the build of a raw file from your source library. +- `module.fileDependencies`: An array of source file paths included into a module. This includes the source JavaScript file itself (ex: `index.js`), and all dependency asset files (stylesheets, images, etc) that it has required. Reviewing dependencies is useful for seeing what source files belong to a module. +- `compilation.chunks`: An array of chunks (build outputs) in the compilation. Each chunk manages the composition of a final rendered assets. +- `chunk.modules`: An array of modules that are included into a chunk. By extension, you may look through each module's dependencies to see what raw source files fed into a chunk. +- `chunk.files`: An array of output filenames generated by the chunk. You may access these asset sources from the `compilation.assets` table. + +### Monitoring the watch graph + +While running webpack middleware, each compilation includes a `fileDependencies` array (what files are being watched) and a `fileTimestamps` hash that maps watched file paths to a timestamp. These are extremely useful for detecting what files have changed within the compilation: + +```javascript +class MyPlugin { + constructor() { + this.startTime = Date.now(); + this.prevTimestamps = {}; + } + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + var changedFiles = Object.keys(compilation.fileTimestamps).filter( + watchfile => { + return ( + (this.prevTimestamps[watchfile] || this.startTime) < + (compilation.fileTimestamps[watchfile] || Infinity) + ); + } + ); + + this.prevTimestamps = compilation.fileTimestamps; + callback(); + }); + } +} + +module.exports = MyPlugin; +``` + +You may also feed new file paths into the watch graph to receive compilation triggers when those files change. Simply push valid file paths into the `compilation.fileDependencies` array to add them to the watch. Note: the `fileDependencies` array is rebuilt in each compilation, so your plugin must push its own watched dependencies into each compilation to keep them under watch. + +## Changed chunks + +Similar to the watch graph, it's fairly simple to monitor changed chunks (or modules, for that matter) within a compilation by tracking their hashes. + +```javascript +class MyPlugin { + constructor() { + this.chunkVersions = {}; + } + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + var changedChunks = compilation.chunks.filter(chunk => { + var oldVersion = this.chunkVersions[chunk.name]; + this.chunkVersions[chunk.name] = chunk.hash; + return chunk.hash !== oldVersion; + }); + callback(); + }); + } +} + +module.exports = MyPlugin; +``` + + +# Release Process + +The release process for deploying webpack is actually quite painless. Read through the following steps, so you have a clear understanding of how it's done. + + +## Pull Requests + +When merging pull requests into the `master` branch, select the _Create Merge Commit_ option. + + +## Releasing + +```sh +npm version patch && git push --follow-tags && npm publish +npm version minor && git push --follow-tags && npm publish +npm version major && git push --follow-tags && npm publish +``` + +_This will increment the package version, commits the changes, cuts a __local tag__, push to github & publish the npm package._ + +After that go to the github [releases page](https://github.com/webpack/webpack/releases) and write a Changelog for the new tag. + + +# Debugging + +When contributing to the core repo, writing a loader/plugin, or even just working on complex project, debugging tools can be central to your workflow. Whether the problem is slow performance on a large project or an unhelpful traceback, the following utilities can make figuring it out less painful. + +- The [`stats` data](/api/stats) made available through [Node](/api/node#stats-object) and the [CLI](/api/cli#common-options). +- Chrome __DevTools__ via `node-nightly` and the latest Node.js versions. + + +## Stats + +Whether you want to sift through [this data](/api/stats) manually or use a tool to process it, the `stats` data can be extremely useful when debugging build issues. We won't go in depth here as there's an [entire page](/api/stats) dedicated to its contents, but know that you can use it to find the following information: + +- The contents of every module. +- The modules contained within every chunk. +- Per module compilation and resolving stats. +- Build errors and warnings. +- The relationships between modules. +- And much more... + +On top of that, the official [analyze tool](https://github.com/webpack/analyse) and [various others](/guides/code-splitting#bundle-analysis) will accept this data and visualize it in various ways. + + +## DevTools + +While [`console`](https://nodejs.org/api/console.html) statements may work well in simpler scenarios, sometimes a more robust solution is needed. As most front-end developers already know, Chrome DevTools are a life saver when debugging web applications, _but they don’t have to stop there_. As of Node v6.3.0+, developers can use the built-in `--inspect` flag to debug a node program in DevTools. + +This gives you the power to easily create breakpoints, debug memory usage, expose and examine objects in the console, and much more. In this short demo, we'll utilize the [`node-nightly`](https://github.com/hemanth/node-nightly) package which provides access to the latest and greatest inspecting capabilities. + +W> The `--inspect` interface has been available since v6.3.0 so feel to try it out with your local version, but be warned that certain features and flags may differ from the ones in this demo. + +Let's start by installing it globally: + +``` bash +npm install --global node-nightly +``` + +Now, we'll need to run it once to finish the installation: + +``` bash +node-nightly +``` + +Now, we can simply use `node-nightly` along with the `--inspect` flag to start our build in any webpack-based project. Note that we cannot run NPM `scripts`, e.g. `npm run build`, so we'll have specify the full `node_modules` path: + +``` bash +node-nightly --inspect ./node_modules/webpack/bin/webpack.js +``` + +Which should output something like: + +``` bash +Debugger listening on ws://127.0.0.1:9229/c624201a-250f-416e-a018-300bbec7be2c +For help see https://nodejs.org/en/docs/inspector +``` + +Now jump to `chrome://inspect` in the browser and you should see any active scripts you've inspected under the _Remote Target_ header. Click the "inspect" link under each script to open a dedicated debugger or the _Open dedicated DevTools for Node_ link for a session that will connect automatically. You can also check out the [NiM extension](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj), a handy Chrome plugin that will automatically open a DevTools tab every time you `--inspect` a script. + +We recommend using the `--inspect-brk` flag which will break on the first statement of the script allowing you to go through the source to set breakpoints and start/stop the build as you please. Also, don't forget that you can still pass arguments to the script. For example, if you have multiple configuration files you could pass `--config webpack.prod.js` to specify the configuration you'd like to debug. diff --git a/src/content/guides/_guides_all.md b/src/content/guides/_guides_all.md new file mode 100644 index 000000000000..dab542340ea2 --- /dev/null +++ b/src/content/guides/_guides_all.md @@ -0,0 +1,4880 @@ + + +# Installation + +This guide goes through the various methods used to install webpack. + + +## Prerequisites + +Before we begin, make sure you have a fresh version of [Node.js](https://nodejs.org/en/) installed. The current Long Term Support (LTS) release is an ideal starting point. You may run into a variety of issues with the older versions as they may be missing functionality webpack and/or its related packages require. + + +## Local Installation + +The latest webpack release is: + +[](https://github.com/webpack/webpack/releases) + +To install the latest release or a specific version, run one of the following commands: + +``` bash +npm install --save-dev webpack +npm install --save-dev webpack@<version> +``` + +If you're using webpack v4 or later, you'll need to install the [CLI](/api/cli/). + +``` bash +npm install --save-dev webpack-cli +``` + +Installing locally is what we recommend for most projects. This makes it easier to upgrade projects individually when breaking changes are introduced. Typically webpack is run via one or more [npm scripts](https://docs.npmjs.com/misc/scripts) which will look for a webpack installation in your local `node_modules` directory: + +```json +"scripts": { + "start": "webpack --config webpack.config.js" +} +``` + +T> To run the local installation of webpack you can access its bin version as `node_modules/.bin/webpack`. + + +## Global Installation + +The following NPM installation will make `webpack` available globally: + +``` bash +npm install --global webpack +``` + +W> Note that this is __not a recommended practice__. Installing globally locks you down to a specific version of webpack and could fail in projects that use a different version. + + +## Bleeding Edge + +If you are enthusiastic about using the latest that webpack has to offer, you can install beta versions or even directly from the webpack repository using the following commands: + +``` bash +npm install webpack@beta +npm install webpack/webpack#<tagname/branchname> +``` + +W> Take caution when installing these bleeding edge releases! They may still contain bugs and therefore should not be used in production. + + +# Getting Started + +Webpack is used to compile JavaScript modules. Once [installed](/guides/installation), you can interface with webpack either from its [CLI](/api/cli) or [API](/api/node). If you're still new to webpack, please read through the [core concepts](/concepts) and [this comparison](/comparison) to learn why you might use it over the other tools that are out in the community. + +## Basic Setup + +First let's create a directory, initialize npm, [install webpack locally](/guides/installation#local-installation), and install the webpack-cli (the tool used to run webpack on the command line): + +``` bash +mkdir webpack-demo && cd webpack-demo +npm init -y +npm install webpack webpack-cli --save-dev +``` + +T> Throughout the Guides we will use `diff` blocks to show you what changes we're making to directories, files, and code. + +Now we'll create the following directory structure, files and their contents: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- index.html ++ |- /src ++ |- index.js +``` + +__src/index.js__ + +``` javascript +function component() { + let element = document.createElement('div'); + + // Lodash, currently included via a script, is required for this line to work + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; +} + +document.body.appendChild(component()); +``` + +__index.html__ + +``` html +<!doctype html> +<html> + <head> + <title>Getting Started</title> + <script src="https://unpkg.com/lodash@4.16.6"></script> + </head> + <body> + <script src="./src/index.js"></script> + </body> +</html> +``` + +We also need to adjust our `package.json` file in order to make sure we mark our package as `private`, as well as removing the `main` entry. This is to prevent an accidental publish of your code. + +T> If you want to learn more about the inner workings of `package.json`, then we recommend reading the [npm documentation](https://docs.npmjs.com/files/package.json). + +__package.json__ + +``` diff + { + "name": "webpack-demo", + "version": "1.0.0", + "description": "", ++ "private": true, +- "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "webpack": "^4.20.2", + "webpack-cli": "^3.1.2" + }, + "dependencies": {} + } +``` + +In this example, there are implicit dependencies between the `<script>` tags. Our `index.js` file depends on `lodash` being included in the page before it runs. This is because `index.js` never explicitly declared a need for `lodash`; it just assumes that the global variable `_` exists. + +There are problems with managing JavaScript projects this way: + +- It is not immediately apparent that the script depends on an external library. +- If a dependency is missing, or included in the wrong order, the application will not function properly. +- If a dependency is included but not used, the browser will be forced to download unnecessary code. + +Let's use webpack to manage these scripts instead. + +## Creating a Bundle + +First we'll tweak our directory structure slightly, separating the "source" code (`/src`) from our "distribution" code (`/dist`). The "source" code is the code that we'll write and edit. The "distribution" code is the minimized and optimized `output` of our build process that will eventually be loaded in the browser: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- /dist ++ |- index.html +- |- index.html + |- /src + |- index.js +``` + +To bundle the `lodash` dependency with `index.js`, we'll need to install the library locally: + +``` bash +npm install --save lodash +``` + +T> When installing a package that will be bundled into your production bundle, you should use `npm install --save`. If you're installing a package for development purposes (e.g. a linter, testing libraries, etc.) then you should use `npm install --save-dev`. More information can be found in the [npm documentation](https://docs.npmjs.com/cli/install). + +Now, lets import `lodash` in our script: + +__src/index.js__ + +``` diff ++ import _ from 'lodash'; ++ + function component() { + let element = document.createElement('div'); + +- // Lodash, currently included via a script, is required for this line to work + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +Now, since we'll be bundling our scripts, we have to update our `index.html` file. Let's remove the lodash `<script>`, as we now `import` it, and modify the other `<script>` tag to load the bundle, instead of the raw `/src` file: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> + <title>Getting Started</title> +- <script src="https://unpkg.com/lodash@4.16.6"></script> + </head> + <body> +- <script src="./src/index.js"></script> ++ <script src="main.js"></script> + </body> + </html> +``` + +In this setup, `index.js` explicitly requires `lodash` to be present, and binds it as `_` (no global scope pollution). By stating what dependencies a module needs, webpack can use this information to build a dependency graph. It then uses the graph to generate an optimized bundle where scripts will be executed in the correct order. + +With that said, let's run `npx webpack`, which will take our script at `src/index.js` as the [entry point](/concepts/entry-points), and will generate `dist/main.js` as the [output](/concepts/output). The `npx` command, which ships with Node 8.2/npm 5.2.0 or higher, runs the webpack binary (`./node_modules/.bin/webpack`) of the webpack package we installed in the beginning: + +``` bash +npx webpack + +... +Built at: 13/06/2018 11:52:07 + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ +``` + +T> Your output may vary a bit, but if the build is successful then you are good to go. Also, don't worry about the warning, we'll tackle that later. + +Open `index.html` in your browser and, if everything went right, you should see the following text: 'Hello webpack'. + + +## Modules + +The [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) statements have been standardized in [ES2015](https://babeljs.io/learn-es2015/) and [are supported in most browsers](https://caniuse.com/#search=modules). Some older browsers still lag behind but webpack supports modules out of the box. + +Behind the scenes, webpack actually "transpiles" the code so that older browsers can also run it. If you inspect `dist/main.js`, you might be able to see how webpack does this, it's quite ingenious! Besides `import` and `export`, webpack supports various other module syntaxes as well, see [Module API](/api/module-methods) for more information. + +Note that webpack will not alter any code other than `import` and `export` statements. If you are using other [ES2015 features](http://es6-features.org/), make sure to [use a transpiler](/loaders/#transpiling) such as [Babel](https://babeljs.io/) or [Bublé](https://buble.surge.sh/guide/) via webpack's [loader system](/concepts/loaders/). + + +## Using a Configuration + +As of version 4, webpack doesn't require any configuration, but most projects will need a more complex setup, which is why webpack supports a [configuration file](/concepts/configuration). This is much more efficient than having to manually type in a lot of commands in the terminal, so let's create one: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- webpack.config.js + |- /dist + |- index.html + |- /src + |- index.js +``` + +__webpack.config.js__ + +``` javascript +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'main.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +Now, let's run the build again but instead using our new configuration file: + +``` bash +npx webpack --config webpack.config.js + +... + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ +``` + +T> If a `webpack.config.js` is present, the `webpack` command picks it up by default. We use the `--config` option here only to show that you can pass a config of any name. This will be useful for more complex configurations that need to be split into multiple files. + +A configuration file allows far more flexibility than simple CLI usage. We can specify loader rules, plugins, resolve options and many other enhancements this way. See the [configuration documentation](/configuration) to learn more. + + +## NPM Scripts + +Given it's not particularly fun to run a local copy of webpack from the CLI, we can set up a little shortcut. Let's adjust our _package.json_ by adding an [npm script](https://docs.npmjs.com/misc/scripts): + +__package.json__ + +``` diff + { + "name": "webpack-demo", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", ++ "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "webpack": "^4.20.2", + "webpack-cli": "^3.1.2" + }, + "dependencies": { + "lodash": "^4.17.5" + } + } +``` + +Now the `npm run build` command can be used in place of the `npx` command we used earlier. Note that within `scripts` we can reference locally installed npm packages by name the same way we did with `npx`. This convention is the standard in most npm-based projects because it allows all contributors to use the same set of common scripts (each with flags like `--config` if necessary). + +Now run the following command and see if your script alias works: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/. +``` + +T> Custom parameters can be passed to webpack by adding two dashes between the `npm run build` command and your parameters, e.g. `npm run build -- --colors`. + + +## Conclusion + +Now that you have a basic build together you should move on to the next guide [`Asset Management`](/guides/asset-management) to learn how to manage assets like images and fonts with webpack. At this point, your project should look like this: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist + |- main.js + |- index.html +|- /src + |- index.js +|- /node_modules +``` + +T> If you're using npm 5, you'll probably also see a `package-lock.json` file in your directory. + +If you want to learn more about webpack's design, you can check out the [basic concepts](/concepts) and [configuration](/configuration) pages. Furthermore, the [API](/api) section digs into the various interfaces webpack offers. + + +# Asset Management + +If you've been following the guides from the start, you will now have a small project that shows "Hello webpack". Now let's try to incorporate some other assets, like images, to see how they can be handled. + +Prior to webpack, front-end developers would use tools like grunt and gulp to process these assets and move them from their `/src` folder into their `/dist` or `/build` directory. The same idea was used for JavaScript modules, but tools like webpack will __dynamically bundle__ all dependencies (creating what's known as a [dependency graph](/concepts/dependency-graph)). This is great because every module now _explicitly states its dependencies_ and we'll avoid bundling modules that aren't in use. + +One of the coolest webpack features is that you can also _include any other type of file_, besides JavaScript, for which there is a loader. This means that the same benefits listed above for JavaScript (e.g. explicit dependencies) can be applied to everything used in building a website or web app. Let's start with CSS, as you may already be familiar with that setup. + +## Setup + +Let's make a minor change to our project before we get started: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> +- <title>Getting Started</title> ++ <title>Asset Management</title> + </head> + <body> +- <script src="./main.js"></script> ++ <script src="./bundle.js"></script> + </body> + </html> +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { +- filename: 'main.js', ++ filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + + +## Loading CSS + +In order to `import` a CSS file from within a JavaScript module, you need to install and add the [style-loader](/loaders/style-loader) and [css-loader](/loaders/css-loader) to your [`module` configuration](/configuration/module): + +``` bash +npm install --save-dev style-loader css-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ module: { ++ rules: [ ++ { ++ test: /\.css$/, ++ use: [ ++ 'style-loader', ++ 'css-loader' ++ ] ++ } ++ ] ++ } + }; +``` + +T> webpack uses a regular expression to determine which files it should look for and serve to a specific loader. In this case any file that ends with `.css` will be served to the `style-loader` and the `css-loader`. + +This enables you to `import './style.css'` into the file that depends on that styling. Now, when that module is run, a `<style>` tag with the stringified css will be inserted into the `<head>` of your html file. + +Let's try it out by adding a new `style.css` file to our project and import it in our `index.js`: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- style.css + |- index.js + |- /node_modules +``` + +__src/style.css__ + +``` css +.hello { + color: red; +} +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import './style.css'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.classList.add('hello'); + + return element; + } + + document.body.appendChild(component()); +``` + +Now run your build command: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +bundle.js 76.4 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +Open up `index.html` in your browser again and you should see that `Hello webpack` is now styled in red. To see what webpack did, inspect the page (don't view the page source, as it won't show you the result) and look at the page's head tags. It should contain our style block that we imported in `index.js`. + +Note that you can, and in most cases should, [minimize css](/plugins/mini-css-extract-plugin/#minimizing-for-production) for better load times in production. On top of that, loaders exist for pretty much any flavor of CSS you can think of -- [postcss](/loaders/postcss-loader), [sass](/loaders/sass-loader), and [less](/loaders/less-loader) to name a few. + + +## Loading Images + +So now we're pulling in our CSS, but what about our images like backgrounds and icons? Using the [file-loader](/loaders/file-loader) we can easily incorporate those in our system as well: + +``` bash +npm install --save-dev file-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, ++ { ++ test: /\.(png|svg|jpg|gif)$/, ++ use: [ ++ 'file-loader' ++ ] ++ } + ] + } + }; +``` + +Now, when you `import MyImage from './my-image.png'`, that image will be processed and added to your `output` directory _and_ the `MyImage` variable will contain the final url of that image after processing. When using the [css-loader](/loaders/css-loader), as shown above, a similar process will occur for `url('./my-image.png')` within your CSS. The loader will recognize this is a local file, and replace the `'./my-image.png'` path with the final path to the image in your `output` directory. The [html-loader](/loaders/html-loader) handles `<img src="./my-image.png" />` in the same manner. + +Let's add an image to our project and see how this works, you can use any image you like: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; + import './style.css'; ++ import Icon from './icon.png'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + element.classList.add('hello'); + ++ // Add the image to our existing div. ++ var myIcon = new Image(); ++ myIcon.src = Icon; ++ ++ element.appendChild(myIcon); + + return element; + } + + document.body.appendChild(component()); +``` + +__src/style.css__ + +``` diff + .hello { + color: red; ++ background: url('./icon.png'); + } +``` + +Let's create a new build and open up the index.html file again: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] + bundle.js 76.7 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +If all went well, you should now see your icon as a repeating background, as well as an `img` element beside our `Hello webpack` text. If you inspect this element, you'll see that the actual filename has changed to something like `5c999da72346a995e7e2718865d019c8.png`. This means webpack found our file in the `src` folder and processed it! + +T> A logical next step from here is minifying and optimizing your images. Check out the [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader) and [url-loader](/loaders/url-loader) for more on how you can enhance your image loading process. + + +## Loading Fonts + +So what about other assets like fonts? The file and url loaders will take any file you load through them and output it to your build directory. This means we can use them for any kind of file, including fonts. Let's update our `webpack.config.js` to handle font files: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + }, ++ { ++ test: /\.(woff|woff2|eot|ttf|otf)$/, ++ use: [ ++ 'file-loader' ++ ] ++ } + ] + } + }; +``` + +Add some font files to your project: + +__project__ + + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- my-font.woff ++ |- my-font.woff2 + |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +With the loader configured and fonts in place, you can incorporate them via an `@font-face` declaration. The local `url(...)` directive will be picked up by webpack just as it was with the image: + +__src/style.css__ + +``` diff ++ @font-face { ++ font-family: 'MyFont'; ++ src: url('./my-font.woff2') format('woff2'), ++ url('./my-font.woff') format('woff'); ++ font-weight: 600; ++ font-style: normal; ++ } + + .hello { + color: red; ++ font-family: 'MyFont'; + background: url('./icon.png'); + } +``` + +Now run a new build and let's see if webpack handled our fonts: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +5439466351d432b73fdb518c6ae9654a.woff2 19.5 KiB [emitted] + 387c65cc923ad19790469cfb5b7cb583.woff 23.4 KiB [emitted] + da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] + bundle.js 77 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +Open up `index.html` again and see if our `Hello webpack` text has changed to the new font. If all is well, you should see the changes. + + +## Loading Data + +Another useful asset that can be loaded is data, like JSON files, CSVs, TSVs, and XML. Support for JSON is actually built-in, similar to NodeJS, meaning `import Data from './data.json'` will work by default. To import CSVs, TSVs, and XML you could use the [csv-loader](https://github.com/theplatapi/csv-loader) and [xml-loader](https://github.com/gisikw/xml-loader). Let's handle loading all three: + +``` bash +npm install --save-dev csv-loader xml-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + }, + { + test: /\.(woff|woff2|eot|ttf|otf)$/, + use: [ + 'file-loader' + ] + }, ++ { ++ test: /\.(csv|tsv)$/, ++ use: [ ++ 'csv-loader' ++ ] ++ }, ++ { ++ test: /\.xml$/, ++ use: [ ++ 'xml-loader' ++ ] ++ } + ] + } + }; +``` + +Add some data files to your project: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- data.xml + |- my-font.woff + |- my-font.woff2 + |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +__src/data.xml__ + +``` xml +<?xml version="1.0" encoding="UTF-8"?> +<note> + <to>Mary</to> + <from>John</from> + <heading>Reminder</heading> + <body>Call Cindy on Tuesday</body> +</note> +``` + +Now you can `import` any one of those four types of data (JSON, CSV, TSV, XML) and the `Data` variable you import it to will contain parsed JSON for easy consumption: + +__src/index.js__ + +``` diff + import _ from 'lodash'; + import './style.css'; + import Icon from './icon.png'; ++ import Data from './data.xml'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + element.classList.add('hello'); + + // Add the image to our existing div. + var myIcon = new Image(); + myIcon.src = Icon; + + element.appendChild(myIcon); + ++ console.log(Data); + + return element; + } + + document.body.appendChild(component()); +``` + +When you open `index.html` and look at your console in your developer tools, you should be able to see your imported data being logged to the console! + +T> This can be especially helpful when implementing some sort of data visualization using a tool like [d3](https://github.com/d3). Instead of making an ajax request and parsing the data at runtime you can load it into your module during the build process so that the parsed data is ready to go as soon as the module hits the browser. + + +## Global Assets + +The coolest part of everything mentioned above, is that loading assets this way allows you to group modules and assets together in a more intuitive way. Instead of relying on a global `/assets` directory that contains everything, you can group assets with the code that uses them. For example, a structure like this can be very useful: + +``` diff +- |- /assets ++ |– /components ++ | |– /my-component ++ | | |– index.jsx ++ | | |– index.css ++ | | |– icon.svg ++ | | |– img.png +``` + +This setup makes your code a lot more portable as everything that is closely coupled now lives together. Let's say you want to use `/my-component` in another project, simply copy or move it into the `/components` directory over there. As long as you've installed any _external dependencies_ and your _configuration has the same loaders_ defined, you should be good to go. + +However, let's say you're locked into your old ways or you have some assets that are shared between multiple components (views, templates, modules, etc.). It's still possible to store these assets in a base directory and even use [aliasing](/configuration/resolve#resolve-alias) to make them easier to `import`. + + +## Wrapping up + +For the next guides we won't be using all the different assets we've used in this guide, so let's do some cleanup so we're prepared for the next piece of the guides [Output Management](https://webpack.js.org/guides/output-management/): + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src +- |- data.xml +- |- my-font.woff +- |- my-font.woff2 +- |- icon.png +- |- style.css + |- index.js + |- /node_modules +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- module: { +- rules: [ +- { +- test: /\.css$/, +- use: [ +- 'style-loader', +- 'css-loader' +- ] +- }, +- { +- test: /\.(png|svg|jpg|gif)$/, +- use: [ +- 'file-loader' +- ] +- }, +- { +- test: /\.(woff|woff2|eot|ttf|otf)$/, +- use: [ +- 'file-loader' +- ] +- }, +- { +- test: /\.(csv|tsv)$/, +- use: [ +- 'csv-loader' +- ] +- }, +- { +- test: /\.xml$/, +- use: [ +- 'xml-loader' +- ] +- } +- ] +- } + }; +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; +- import './style.css'; +- import Icon from './icon.png'; +- import Data from './data.xml'; +- + function component() { + var element = document.createElement('div'); +- +- // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- element.classList.add('hello'); +- +- // Add the image to our existing div. +- var myIcon = new Image(); +- myIcon.src = Icon; +- +- element.appendChild(myIcon); +- +- console.log(Data); + + return element; + } + + document.body.appendChild(component()); +``` + + +## Next guide + +Let's move on to [Output Management](https://webpack.js.org/guides/output-management/) + + +## Further Reading + +- [Loading Fonts](https://survivejs.com/webpack/loading/fonts/) on SurviveJS + + +# Output Management + +T> This guide extends on code examples found in the [`Asset Management`](/guides/asset-management) guide. + +So far we've manually included all our assets in our `index.html` file, but as your application grows and once you start [using hashes in filenames](/guides/caching) and outputting [multiple bundles](/guides/code-splitting), it will be difficult to keep managing your `index.html` file manually. However, a few plugins exist that will make this process much easier to manage. + +## Preparation + +First, let's adjust our project a little bit: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js ++ |- print.js + |- /node_modules +``` + +Let's add some logic to our `src/print.js` file: + +__src/print.js__ + +``` js +export default function printMe() { + console.log('I get called from print.js!'); +} +``` + +And use that function in our `src/index.js` file: + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); ++ var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + ++ btn.innerHTML = 'Click me and check the console!'; ++ btn.onclick = printMe; ++ ++ element.appendChild(btn); + + return element; + } + + document.body.appendChild(component()); +``` + +Let's also update our `dist/index.html` file, in preparation for webpack to split out entries: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> +- <title>Asset Management</title> ++ <title>Output Management</title> ++ <script src="./print.bundle.js"></script> + </head> + <body> +- <script src="./bundle.js"></script> ++ <script src="./app.bundle.js"></script> + </body> + </html> +``` + +Now adjust the config. We'll be adding our `src/print.js` as a new entry point (`print`) and we'll change the output as well, so that it will dynamically generate bundle names, based on the entry point names: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { +- entry: './src/index.js', ++ entry: { ++ app: './src/index.js', ++ print: './src/print.js' ++ }, + output: { +- filename: 'bundle.js', ++ filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Let's run `npm run build` and see what this generates: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 545 kB 0, 1 [emitted] [big] app +print.bundle.js 2.74 kB 1 [emitted] print +... +``` + +We can see that webpack generates our `print.bundle.js` and `app.bundle.js` files, which we also specified in our `index.html` file. if you open `index.html` in your browser, you can see what happens when you click the button. + +But what would happen if we changed the name of one of our entry points, or even added a new one? The generated bundles would be renamed on a build, but our `index.html` file would still reference the old names. Let's fix that with the [`HtmlWebpackPlugin`](/plugins/html-webpack-plugin). + + +## Setting up HtmlWebpackPlugin + +First install the plugin and adjust the `webpack.config.js` file: + +``` bash +npm install --save-dev html-webpack-plugin +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, ++ plugins: [ ++ new HtmlWebpackPlugin({ ++ title: 'Output Management' ++ }) ++ ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Before we do a build, you should know that the `HtmlWebpackPlugin` by default will generate its own `index.html` file, even though we already have one in the `dist/` folder. This means that it will replace our `index.html` file with a newly generated one. Let's see what happens when we do an `npm run build`: + +``` bash +... + Asset Size Chunks Chunk Names + print.bundle.js 544 kB 0 [emitted] [big] print + app.bundle.js 2.81 kB 1 [emitted] app + index.html 249 bytes [emitted] +... +``` + +If you open `index.html` in your code editor, you'll see that the `HtmlWebpackPlugin` has created an entirely new file for you and that all the bundles are automatically added. + +If you want to learn more about all the features and options that the `HtmlWebpackPlugin` provides, then you should read up on it on the [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin) repo. + +You can also take a look at [`html-webpack-template`](https://github.com/jaketrent/html-webpack-template) which provides a couple of extra features in addition to the default template. + + +## Cleaning up the `/dist` folder + +As you might have noticed over the past guides and code example, our `/dist` folder has become quite cluttered. Webpack will generate the files and put them in the `/dist` folder for you, but it doesn't keep track of which files are actually in use by your project. + +In general it's good practice to clean the `/dist` folder before each build, so that only used files will be generated. Let's take care of that. + +A popular plugin to manage this is the [`clean-webpack-plugin`](https://www.npmjs.com/package/clean-webpack-plugin) so let's install and configure it. + +``` bash +npm install --save-dev clean-webpack-plugin +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); ++ const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ ++ new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Output Management' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Now run an `npm run build` and inspect the `/dist` folder. If everything went well you should now only see the files generated from the build and no more old files! + + +## The Manifest + +You might be wondering how webpack and its plugins seem to "know" what files are being generated. The answer is in the manifest that webpack keeps to track how all the modules map to the output bundles. If you're interested in managing webpack's [`output`](/configuration/output) in other ways, the manifest would be a good place to start. + +The manifest data can be extracted into a json file for easy consumption using the [`WebpackManifestPlugin`](https://github.com/danethurber/webpack-manifest-plugin). + +We won't go through a full example of how to use this plugin within your projects, but you can read up on [the concept page](/concepts/manifest) and the [caching guide](/guides/caching) to find out how this ties into long term caching. + + +## Conclusion + +Now that you've learned about dynamically adding bundles to your HTML, let's dive into the [development guide](/guides/development). Or, if you want to dig into more advanced topics, we would recommend heading over to the [code splitting guide](/guides/code-splitting). + + +# Development + +T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. + +If you've been following the guides, you should have a solid understanding of some of the webpack basics. Before we continue, let's look into setting up a development environment to make our lives a little easier. + +W> The tools in this guide are __only meant for development__, please __avoid__ using them in production! + +Before proceeding lets first set [`mode` to `'development'`](/concepts/mode/#mode-development). + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { ++ mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +## Using source maps + +When webpack bundles your source code, it can become difficult to track down errors and warnings to their original location. For example, if you bundle three source files (`a.js`, `b.js`, and `c.js`) into one bundle (`bundle.js`) and one of the source files contains an error, the stack trace will simply point to `bundle.js`. This isn't always helpful as you probably want to know exactly which source file the error came from. + +In order to make it easier to track down errors and warnings, JavaScript offers [source maps](http://blog.teamtreehouse.com/introduction-source-maps), which maps your compiled code back to your original source code. If an error originates from `b.js`, the source map will tell you exactly that. + +There are a lot of [different options](/configuration/devtool) available when it comes to source maps. Be sure to check them out so you can configure them to your needs. + +For this guide, let's use the `inline-source-map` option, which is good for illustrative purposes (though not for production): + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, ++ devtool: 'inline-source-map', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Now let's make sure we have something to debug, so let's create an error in our `print.js` file: + +__src/print.js__ + +``` diff + export default function printMe() { +- console.log('I get called from print.js!'); ++ cosnole.log('I get called from print.js!'); + } +``` + +Run an `npm run build`, it should compile to something like this: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 1.44 MB 0, 1 [emitted] [big] app +print.bundle.js 6.43 kB 1 [emitted] print + index.html 248 bytes [emitted] +... +``` + +Now open the resulting `index.html` file in your browser. Click the button and look in your console where the error is displayed. The error should say something like this: + + ``` bash + Uncaught ReferenceError: cosnole is not defined + at HTMLButtonElement.printMe (print.js:2) + ``` + +We can see that the error also contains a reference to the file (`print.js`) and line number (2) where the error occurred. This is great because now we know exactly where to look in order to fix the issue. + + +## Choosing a Development Tool + +W> Some text editors have a "safe write" function that might interfere with some of the following tools. Read [Adjusting Your text Editor](#adjusting-your-text-editor) for a solution to these issues. + +It quickly becomes a hassle to manually run `npm run build` every time you want to compile your code. + +There are a couple of different options available in webpack that help you automatically compile your code whenever it changes: + + 1. webpack's Watch Mode + 2. webpack-dev-server + 3. webpack-dev-middleware + +In most cases, you probably would want to use `webpack-dev-server`, but let's explore all of the above options. + + +### Using Watch Mode + +You can instruct webpack to "watch" all files within your dependency graph for changes. If one of these files is updated, the code will be recompiled so you don't have to run the full build manually. + +Let's add an npm script that will start webpack's Watch Mode: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", ++ "watch": "webpack --watch", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now run `npm run watch` from the command line and see how webpack compiles your code. +You can see that it doesn't exit the command line because the script is currently watching your files. + +Now, while webpack is watching your files, let's remove the error we introduced earlier: + +__src/print.js__ + +``` diff + export default function printMe() { +- cosnole.log('I get called from print.js!'); ++ console.log('I get called from print.js!'); + } +``` + +Now save your file and check the terminal window. You should see that webpack automatically recompiles the changed module! + +The only downside is that you have to refresh your browser in order to see the changes. It would be much nicer if that would happen automatically as well, so let's try `webpack-dev-server` which will do exactly that. + + +### Using webpack-dev-server + +The `webpack-dev-server` provides you with a simple web server and the ability to use live reloading. Let's set it up: + +``` bash +npm install --save-dev webpack-dev-server +``` + +Change your config file to tell the dev server where to look for files: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + devtool: 'inline-source-map', ++ devServer: { ++ contentBase: './dist' ++ }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +This tells `webpack-dev-server` to serve the files from the `dist` directory on `localhost:8080`. + +W> webpack-dev-server doesn't write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server's root path. If your page expects to find the bundle files in different path, you can change this with the [`publicPath`](/configuration/dev-server/#devserver-publicpath-) option in the dev server's configuration. + +Let's add a script to easily run the dev server as well: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "watch": "webpack --watch", ++ "start": "webpack-dev-server --open", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now we can run `npm start` from the command line and we will see our browser automatically loading up our page. If you now change any of the source files and save them, the web server will automatically reload after the code has been compiled. Give it a try! + +The `webpack-dev-server` comes with many configurable options. Head over to the [documentation](/configuration/dev-server) to learn more. + +T> Now that your server is working, you might want to give [Hot Module Replacement](/guides/hot-module-replacement) a try! + + +### Using webpack-dev-middleware + +`webpack-dev-middleware` is a wrapper that will emit files processed by webpack to a server. This is used in `webpack-dev-server` internally, however it's available as a separate package to allow more custom setups if desired. We'll take a look at an example that combines webpack-dev-middleware with an express server. + +Let's install `express` and `webpack-dev-middleware` so we can get started: + +``` bash +npm install --save-dev express webpack-dev-middleware +``` + +Now we need to make some adjustments to our webpack configuration file in order to make sure the middleware will function correctly: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Output Management' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist'), ++ publicPath: '/' + } + }; +``` + +The `publicPath` will be used within our server script as well in order to make sure files are served correctly on `http://localhost:3000`. We'll specify the port number later. The next step is setting up our custom `express` server: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js ++ |- server.js + |- /dist + |- /src + |- index.js + |- print.js + |- /node_modules +``` + +__server.js__ + +```javascript +const express = require('express'); +const webpack = require('webpack'); +const webpackDevMiddleware = require('webpack-dev-middleware'); + +const app = express(); +const config = require('./webpack.config.js'); +const compiler = webpack(config); + +// Tell express to use the webpack-dev-middleware and use the webpack.config.js +// configuration file as a base. +app.use(webpackDevMiddleware(compiler, { + publicPath: config.output.publicPath +})); + +// Serve the files on port 3000. +app.listen(3000, function () { + console.log('Example app listening on port 3000!\n'); +}); +``` + +Now add an npm script to make it a little easier to run the server: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "watch": "webpack --watch", + "start": "webpack-dev-server --open", ++ "server": "node server.js", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "express": "^4.15.3", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "webpack-dev-middleware": "^1.12.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now in your terminal run `npm run server`, it should give you an output similar to this: + +``` bash +Example app listening on port 3000! +... + Asset Size Chunks Chunk Names + app.bundle.js 1.44 MB 0, 1 [emitted] [big] app +print.bundle.js 6.57 kB 1 [emitted] print + index.html 306 bytes [emitted] +... +webpack: Compiled successfully. +``` + +Now fire up your browser and go to `http://localhost:3000`. You should see your webpack app running and functioning! + +T> If you would like to know more about how Hot Module Replacement works, we recommend you read the [Hot Module Replacement](/guides/hot-module-replacement/) guide. + + +## Adjusting Your Text Editor + +When using automatic compilation of your code, you could run into issues when saving your files. Some editors have a "safe write" feature that can potentially interfere with recompilation. + +To disable this feature in some common editors, see the list below: + +- __Sublime Text 3__: Add `atomic_save: 'false'` to your user preferences. +- __JetBrains IDEs (e.g. WebStorm)__: Uncheck "Use safe write" in `Preferences > Appearance & Behavior > System Settings`. +- __Vim__: Add `:set backupcopy=yes` to your settings. + + +## Conclusion + +Now that you've learned how to automatically compile your code and run a simple development server, you can check out the next guide, which will cover [Hot Module Replacement](/guides/hot-module-replacement). + + +# Hot Module Replacement + +T> This guide extends on code examples found in the [Development](/guides/development) guide. + +Hot Module Replacement (or HMR) is one of the most useful features offered by webpack. It allows all kinds of modules to be updated at runtime without the need for a full refresh. This page focuses on __implementation__ while the [concepts page](/concepts/hot-module-replacement) gives more details on how it works and why it's useful. + +W> __HMR__ is not intended for use in production, meaning it should only be used in development. See the [building for production guide](/guides/production) for more information. + + +## Enabling HMR + +This feature is great for productivity. All we need to do is update our [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration, and use webpack's built in HMR plugin. We'll also remove the entry point for `print.js` as it will now be consumed by the `index.js` module. + +T> If you took the route of using `webpack-dev-middleware` instead of `webpack-dev-server`, please use the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom server or application. + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const webpack = require('webpack'); + + module.exports = { + entry: { +- app: './src/index.js', +- print: './src/print.js' ++ app: './src/index.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist', ++ hot: true + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Hot Module Replacement' + }), ++ new webpack.HotModuleReplacementPlugin() + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +T> You can use the CLI to modify the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration with the following command: `webpack-dev-server --hotOnly`. + +Now let's update the `index.js` file so that when a change inside `print.js` is detected we tell webpack to accept the updated module. + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; + + element.appendChild(btn); + + return element; + } + + document.body.appendChild(component()); ++ ++ if (module.hot) { ++ module.hot.accept('./print.js', function() { ++ console.log('Accepting the updated printMe module!'); ++ printMe(); ++ }) ++ } +``` + +Start changing the `console.log` statement in `print.js`, and you should see the following output in the browser console. + +__print.js__ + +``` diff + export default function printMe() { +- console.log('I get called from print.js!'); ++ console.log('Updating print.js...') + } +``` + +__console__ + +``` diff +[HMR] Waiting for update signal from WDS... +main.js:4395 [WDS] Hot Module Replacement enabled. ++ 2main.js:4395 [WDS] App updated. Recompiling... ++ main.js:4395 [WDS] App hot update... ++ main.js:4330 [HMR] Checking for updates on the server... ++ main.js:10024 Accepting the updated printMe module! ++ 0.4b8ee77….hot-update.js:10 Updating print.js... ++ main.js:4330 [HMR] Updated modules: ++ main.js:4330 [HMR] - 20 +``` + + +## Via the Node.js API + +When using Webpack Dev Server with the Node.js API, don't put the dev server options on the webpack config object. Instead, pass them as a second parameter upon creation. For example: + +`new WebpackDevServer(compiler, options)` + +To enable HMR, you also need to modify your webpack configuration object to include the HMR entry points. The `webpack-dev-server` package includes a method called `addDevServerEntrypoints` which you can use to do this. Here's a small example of how that might look: + +__dev-server.js__ + +``` javascript +const webpackDevServer = require('webpack-dev-server'); +const webpack = require('webpack'); + +const config = require('./webpack.config.js'); +const options = { + contentBase: './dist', + hot: true, + host: 'localhost' +}; + +webpackDevServer.addDevServerEntrypoints(config, options); +const compiler = webpack(config); +const server = new webpackDevServer(compiler, options); + +server.listen(5000, 'localhost', () => { + console.log('dev server listening on port 5000'); +}); +``` + +T> If you're [using `webpack-dev-middleware`](/guides/development#using-webpack-dev-middleware), check out the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom dev server. + + +## Gotchas + +Hot Module Replacement can be tricky. To show this, let's go back to our working example. If you go ahead and click the button on the example page, you will realize the console is printing the old `printMe` function. + +This is happening because the button's `onclick` event handler is still bound to the original `printMe` function. + +To make this work with HMR we need to update that binding to the new `printMe` function using `module.hot.accept`: + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; // onclick event is bind to the original printMe function + + element.appendChild(btn); + + return element; + } + +- document.body.appendChild(component()); ++ let element = component(); // Store the element to re-render on print.js changes ++ document.body.appendChild(element); + + if (module.hot) { + module.hot.accept('./print.js', function() { + console.log('Accepting the updated printMe module!'); +- printMe(); ++ document.body.removeChild(element); ++ element = component(); // Re-render the "component" to update the click handler ++ document.body.appendChild(element); + }) + } +``` + +This is just one example, but there are many others that can easily trip people up. Luckily, there are a lot of loaders out there (some of which are mentioned below) that will make hot module replacement much easier. + + +## HMR with Stylesheets + +Hot Module Replacement with CSS is actually fairly straightforward with the help of the `style-loader`. This loader uses `module.hot.accept` behind the scenes to patch `<style>` tags when CSS dependencies are updated. + +First let's install both loaders with the following command: + +```bash +npm install --save-dev style-loader css-loader +``` + +Now let's update the configuration file to make use of the loader. + +__webpack.config.js__ + +```diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const webpack = require('webpack'); + + module.exports = { + entry: { + app: './src/index.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist', + hot: true + }, ++ module: { ++ rules: [ ++ { ++ test: /\.css$/, ++ use: ['style-loader', 'css-loader'] ++ } ++ ] ++ }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Hot Module Replacement' + }), + new webpack.HotModuleReplacementPlugin() + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Hot loading stylesheets is as easy as importing them into a module: + +__project__ + +``` diff + webpack-demo + | - package.json + | - webpack.config.js + | - /dist + | - bundle.js + | - /src + | - index.js + | - print.js ++ | - styles.css +``` + +__styles.css__ + +``` css +body { + background: blue; +} +``` + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; ++ import './styles.css'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; // onclick event is bind to the original printMe function + + element.appendChild(btn); + + return element; + } + + let element = component(); + document.body.appendChild(element); + + if (module.hot) { + module.hot.accept('./print.js', function() { + console.log('Accepting the updated printMe module!'); + document.body.removeChild(element); + element = component(); // Re-render the "component" to update the click handler + document.body.appendChild(element); + }) + } + +``` + +Change the style on `body` to `background: red;` and you should immediately see the page's background color change without a full refresh. + +__styles.css__ + +``` diff + body { +- background: blue; ++ background: red; + } +``` + + +## Other Code and Frameworks + +There are many other loaders and examples out in the community to make HMR interact smoothly with a variety of frameworks and libraries... + +- [React Hot Loader](https://github.com/gaearon/react-hot-loader): Tweak react components in real time. +- [Vue Loader](https://github.com/vuejs/vue-loader): This loader supports HMR for vue components out of the box. +- [Elm Hot Loader](https://github.com/fluxxu/elm-hot-loader): Supports HMR for the Elm programming language. +- [Angular HMR](https://github.com/gdi2290/angular-hmr): No loader necessary! A simple change to your main NgModule file is all that's required to have full control over the HMR APIs. + +T> If you know of any other loaders or plugins that help with or enhance Hot Module Replacement please submit a pull request to add to this list! + + +# Tree Shaking + +_Tree shaking_ is a term commonly used in the JavaScript context for dead-code elimination. It relies on the [static structure](http://exploringjs.com/es6/ch_modules.html#static-module-structure) of ES2015 module syntax, i.e. [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export). The name and concept have been popularized by the ES2015 module bundler [rollup](https://github.com/rollup/rollup). + +The webpack 2 release came with built-in support for ES2015 modules (alias _harmony modules_) as well as unused module export detection. The new webpack 4 release expands on this capability with a way to provide hints to the compiler via the `"sideEffects"` `package.json` property to denote which files in your project are "pure" and therefore safe to prune if unused. + +T> The remainder of this guide will stem from [Getting Started](/guides/getting-started). If you haven't read through that guide already, please do so now. + + +## Add a Utility + +Let's add a new utility file to our project, `src/math.js`, that exports two functions: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist + |- bundle.js + |- index.html +|- /src + |- index.js ++ |- math.js +|- /node_modules +``` + +__src/math.js__ + +```javascript +export function square(x) { + return x * x; +} + +export function cube(x) { + return x * x * x; +} +``` + +Set the `mode` configuration option to [development](/concepts/mode/#mode-development) to make sure that the bundle is not minified: + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') +- } ++ }, ++ mode: 'development', ++ optimization: { ++ usedExports: true ++ } +}; +``` + +With that in place, let's update our entry script to utilize one of these new methods and remove `lodash` for simplicity: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; ++ import { cube } from './math.js'; + + function component() { +- var element = document.createElement('div'); ++ var element = document.createElement('pre'); + +- // Lodash, now imported by this script +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.innerHTML = [ ++ 'Hello webpack!', ++ '5 cubed is equal to ' + cube(5) ++ ].join('\n\n'); + + return element; + } + + document.body.appendChild(component()); +``` + +Note that we __did not `import` the `square` method__ from the `src/math.js` module. That function is what's known as "dead code", meaning an unused `export` that should be dropped. Now let's run our npm script, `npm run build`, and inspect the output bundle: + +__dist/bundle.js (around lines 90 - 100)__ + +```js +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + 'use strict'; + /* unused harmony export square */ + /* harmony export (immutable) */ __webpack_exports__['a'] = cube; + function square(x) { + return x * x; + } + + function cube(x) { + return x * x * x; + } +}); +``` + +Note the `unused harmony export square` comment above. If you look at the code below it, you'll notice that `square` is not being imported, however, it is still included in the bundle. We'll fix that in the next section. + + +## Mark the file as side-effect-free + +In a 100% ESM module world, identifying side effects is straightforward. However, we aren't there just yet, so in the mean time it's necessary to provide hints to webpack's compiler on the "pureness" of your code. + +The way this is accomplished is the `"sideEffects"` package.json property. + +```json +{ + "name": "your-project", + "sideEffects": false +} +``` + +All the code noted above does not contain side effects, so we can simply mark the property as `false` to inform webpack that it can safely prune unused exports. + +T> A "side effect" is defined as code that performs a special behavior when imported, other than exposing one or more exports. An example of this are polyfills, which affect the global scope and usually do not provide an export. + +If your code did have some side effects though, an array can be provided instead: + +```json +{ + "name": "your-project", + "sideEffects": [ + "./src/some-side-effectful-file.js" + ] +} +``` + +The array accepts relative, absolute, and glob patterns to the relevant files. It uses [micromatch](https://github.com/micromatch/micromatch#matching-features) under the hood. + +T> Note that any imported file is subject to tree shaking. This means if you use something like `css-loader` in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode: + +```json +{ + "name": "your-project", + "sideEffects": [ + "./src/some-side-effectful-file.js", + "*.css" + ] +} +``` + +Finally, `"sideEffects"` can also be set from the [`module.rules` configuration option](/configuration/module/#module-rules). + +## Minify the Output + +So we've cued up our "dead code" to be dropped by using the `import` and `export` syntax, but we still need to drop it from the bundle. To do that set the `mode` configuration option to [`production`](/concepts/mode/#mode-production) configuration option. + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- mode: 'development', +- optimization: { +- usedExports: true +- } ++ mode: 'production' +}; +``` + +T> Note that the `--optimize-minimize` flag can be used to enable `TerserPlugin` as well. + +With that squared away, we can run another `npm run build` and see if anything has changed. + +Notice anything different about `dist/bundle.js`? Clearly the whole bundle is now minified and mangled, but, if you look carefully, you won't see the `square` function included but will see a mangled version of the `cube` function (`function r(e){return e*e*e}n.a=r`). With minification and tree shaking our bundle is now a few bytes smaller! While that may not seem like much in this contrived example, tree shaking can yield a significant decrease in bundle size when working on larger applications with complex dependency trees. + +T> [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) is needed for the tree shaking to work. It is added by `mode: "production"`. If you are not using it, remember to add the [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) manually. + +## Conclusion + +So, what we've learned is that in order to take advantage of _tree shaking_, you must... + +- Use ES2015 module syntax (i.e. `import` and `export`). +- Ensure no compilers transform your ES2015 module syntax into CommonJS modules (this is the default behavior of popular Babel preset @babel/preset-env - see [documentation](https://babeljs.io/docs/en/babel-preset-env#modules) for more details). +- Add a `"sideEffects"` property to your project's `package.json` file. +- Use [`production`](/concepts/mode/#mode-production) `mode` configuration option to enable [various optimizations](/concepts/mode/#usage) including minification and tree shaking. + +You can imagine your application as a tree. The source code and libraries you actually use represent the green, living leaves of the tree. Dead code represents the brown, dead leaves of the tree that are consumed by autumn. In order to get rid of the dead leaves, you have to shake the tree, causing them to fall. + +If you are interested in more ways to optimize your output, please jump to the next guide for details on building for [production](/guides/production). + + +# Production + +In this guide we'll dive into some of the best practices and utilities for building a production site or application. + +T> This walkthrough stems from [Tree Shaking](/guides/tree-shaking) and [Development](/guides/development). Please ensure you are familiar with the concepts/setup introduced in those guides before continuing on. + + +## Setup + +The goals of _development_ and _production_ builds differ greatly. In _development_, we want strong source mapping and a localhost server with live reloading or hot module replacement. In _production_, our goals shift to a focus on minified bundles, lighter weight source maps, and optimized assets to improve load time. With this logical separation at hand, we typically recommend writing __separate webpack configurations__ for each environment. + +While we will separate the _production_ and _development_ specific bits out, note that we'll still maintain a "common" configuration to keep things DRY. In order to merge these configurations together, we'll use a utility called [`webpack-merge`](https://github.com/survivejs/webpack-merge). With the "common" configuration in place, we won't have to duplicate code within the environment-specific configurations. + +Let's start by installing `webpack-merge` and splitting out the bits we've already worked on in previous guides: + +``` bash +npm install --save-dev webpack-merge +``` + +__project__ + +``` diff + webpack-demo + |- package.json +- |- webpack.config.js ++ |- webpack.common.js ++ |- webpack.dev.js ++ |- webpack.prod.js + |- /dist + |- /src + |- index.js + |- math.js + |- /node_modules +``` + +__webpack.common.js__ + +``` diff ++ const path = require('path'); ++ const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const HtmlWebpackPlugin = require('html-webpack-plugin'); ++ ++ module.exports = { ++ entry: { ++ app: './src/index.js' ++ }, ++ plugins: [ ++ new CleanWebpackPlugin(['dist']), ++ new HtmlWebpackPlugin({ ++ title: 'Production' ++ }) ++ ], ++ output: { ++ filename: '[name].bundle.js', ++ path: path.resolve(__dirname, 'dist') ++ } ++ }; +``` + +__webpack.dev.js__ + +``` diff ++ const merge = require('webpack-merge'); ++ const common = require('./webpack.common.js'); ++ ++ module.exports = merge(common, { ++ mode: 'development', ++ devtool: 'inline-source-map', ++ devServer: { ++ contentBase: './dist' ++ } ++ }); +``` + +__webpack.prod.js__ + +``` diff ++ const merge = require('webpack-merge'); ++ const common = require('./webpack.common.js'); ++ ++ module.exports = merge(common, { ++ mode: 'production', ++ }); +``` + +In `webpack.common.js`, we now have setup our `entry` and `output` configuration and we've included any plugins that are required for both environments. In `webpack.dev.js`, we've set ``mode`` to ``development``. Also, we've added the recommended `devtool` for that environment (strong source mapping), as well as our simple `devServer` configuration. Finally, in `webpack.prod.js`,``mode`` is set to ``production`` which loads `TerserPlugin` which was first introduced by the [tree shaking](/guides/tree-shaking) guide. + +Note the use of `merge()` in the environment-specific configurations to easily include our common configuration in `dev` and `prod`. The `webpack-merge` tool offers a variety of advanced features for merging but for our use case we won't need any of that. + + +## NPM Scripts + +Now let's repoint our `scripts` to the new configurations. We'll use the _development_ one for our `webpack-dev-server`, `npm start`, script and the _production_ one for our `npm run build` script: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { +- "start": "webpack-dev-server --open", ++ "start": "webpack-dev-server --open --config webpack.dev.js", +- "build": "webpack" ++ "build": "webpack --config webpack.prod.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.17", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "express": "^4.15.3", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "webpack-dev-middleware": "^1.12.0", + "webpack-dev-server": "^2.9.1", + "webpack-merge": "^4.1.0", + "xml-loader": "^1.2.1" + } + } +``` + +Feel free to run those scripts and see how the output changes as we continue adding to our _production_ configuration. + + +## Specify the Mode + +Many libraries will key off the `process.env.NODE_ENV` variable to determine what should be included in the library. For example, when not in _production_ some libraries may add additional logging and testing to make debugging easier. However, with `process.env.NODE_ENV === 'production'` they might drop or add significant portions of code to optimize how things run for your actual users. Since webpack v4, specifying [`mode`](/concepts/mode/) automatically configures [`DefinePlugin`](/plugins/define-plugin) for you: + +__webpack.prod.js__ + +``` diff + const merge = require('webpack-merge'); + const common = require('./webpack.common.js'); + + module.exports = merge(common, { + mode: 'production', + }); +``` + +T> Technically, `NODE_ENV` is a system environment variable that Node.js exposes into running scripts. It is used by convention to determine dev-vs-prod behavior by server tools, build scripts, and client-side libraries. Contrary to expectations, `process.env.NODE_ENV` is not set to `"production"` __within__ the build script `webpack.config.js`, see [#2537](https://github.com/webpack/webpack/issues/2537). Thus, conditionals like `process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'` within webpack configurations do not work as expected. + +If you're using a library like [`react`](https://reactjs.org/), you should actually see a significant drop in bundle size after adding this plugin. Also note that any of our local `/src` code can key off of this as well, so the following check would be valid: + +__src/index.js__ + +``` diff + import { cube } from './math.js'; ++ ++ if (process.env.NODE_ENV !== 'production') { ++ console.log('Looks like we are in development mode!'); ++ } + + function component() { + var element = document.createElement('pre'); + + element.innerHTML = [ + 'Hello webpack!', + '5 cubed is equal to ' + cube(5) + ].join('\n\n'); + + return element; + } + + document.body.appendChild(component()); +``` + + +## Minification + +webpack v4+ will minify your code by default in [`production mode`](/concepts/mode/#mode-production). + +Note that while the [`TerserPlugin`](/plugins/terser-webpack-plugin) is a great place to start for minification and being used by default, there are other options out there. Here are a few more popular ones: + +- [`BabelMinifyWebpackPlugin`](https://github.com/webpack-contrib/babel-minify-webpack-plugin) +- [`ClosureCompilerPlugin`](https://github.com/roman01la/webpack-closure-compiler) + +If you decide to try another minification plugin, just make sure your new choice also drops dead code as described in the [tree shaking](/guides/tree-shaking) guide and provide it as the [`optimization.minimizer`](/configuration/optimization/#optimization-minimizer). + + +## Source Mapping + +We encourage you to have source maps enabled in production, as they are useful for debugging as well as running benchmark tests. That said, you should choose one with a fairly quick build speed that's recommended for production use (see [`devtool`](/configuration/devtool)). For this guide, we'll use the `source-map` option in _production_ as opposed to the `inline-source-map` we used in _development_: + +__webpack.prod.js__ + +``` diff + const merge = require('webpack-merge'); + const common = require('./webpack.common.js'); + + module.exports = merge(common, { + mode: 'production', ++ devtool: 'source-map' + }); +``` + +T> Avoid `inline-***` and `eval-***` use in production as they can increase bundle size and reduce the overall performance. + + +## Minimize CSS + +It is crucial to minimize your CSS on production, please see [Minimizing for Production](/plugins/mini-css-extract-plugin/#minimizing-for-production) section. + + +## CLI Alternatives + +Some of what has been described above is also achievable via the command line. For example, the `--optimize-minimize` flag will include the `TerserPlugin` behind the scenes. The `--define process.env.NODE_ENV="'production'"` will do the same for the `DefinePlugin` instance described above. And, `webpack -p` will automatically invoke both those flags and thus the plugins to be included. + +While these short hand methods are nice, we usually recommend just using the configuration as it's better to understand exactly what is being done for you in both cases. The configuration also gives you more control on fine tuning other options within both plugins. + + +# Code Splitting + +T> This guide extends the examples provided in [Getting Started](/guides/getting-started) and [Output Management](/guides/output-management). Please make sure you are at least familiar with the examples provided in them. + +Code splitting is one of the most compelling features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel. It can be used to achieve smaller bundles and control resource load prioritization which, if used correctly, can have a major impact on load time. + +There are three general approaches to code splitting available: + +- Entry Points: Manually split code using [`entry`](/configuration/entry-context) configuration. +- Prevent Duplication: Use the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) to dedupe and split chunks. +- Dynamic Imports: Split code via inline function calls within modules. + + +## Entry Points + +This is by far the easiest, and most intuitive, way to split code. However, it is more manual and has some pitfalls we will go over. Let's take a look at how we might split another module from the main bundle: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- another-module.js +|- /node_modules +``` + +__another-module.js__ + +``` js +import _ from 'lodash'; + +console.log( + _.join(['Another', 'module', 'loaded!'], ' ') +); +``` + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + mode: 'development', + entry: { + index: './src/index.js', ++ another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +This will yield the following build result: + +``` bash +... + Asset Size Chunks Chunk Names +another.bundle.js 550 KiB another [emitted] another + index.bundle.js 550 KiB index [emitted] index +Entrypoint index = index.bundle.js +Entrypoint another = another.bundle.js +... +``` + +As mentioned there are some pitfalls to this approach: + +- If there are any duplicated modules between entry chunks they will be included in both bundles. +- It isn't as flexible and can't be used to dynamically split code with the core application logic. + +The first of these two points is definitely an issue for our example, as `lodash` is also imported within `./src/index.js` and will thus be duplicated in both bundles. Let's remove this duplication by using the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). + + +## Prevent Duplication + +The [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) allows us to extract common dependencies into an existing entry chunk or an entirely new chunk. Let's use this to de-duplicate the `lodash` dependency from the previous example: + +W> The `CommonsChunkPlugin` has been removed in webpack v4 legato. To learn how chunks are treated in the latest version, check out the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + mode: 'development', + entry: { + index: './src/index.js', + another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ optimization: { ++ splitChunks: { ++ chunks: 'all' ++ } ++ } + }; +``` + +With the [`optimization.splitChunks`](/plugins/split-chunks-plugin/#optimization-splitchunks) configuration option in place, we should now see the duplicate dependency removed from our `index.bundle.js` and `another.bundle.js`. The plugin should notice that we've separated `lodash` out to a separate chunk and remove the dead weight from our main bundle. Let's do an `npm run build` to see if it worked: + +``` bash +... + Asset Size Chunks Chunk Names + another.bundle.js 5.95 KiB another [emitted] another + index.bundle.js 5.89 KiB index [emitted] index +vendors~another~index.bundle.js 547 KiB vendors~another~index [emitted] vendors~another~index +Entrypoint index = vendors~another~index.bundle.js index.bundle.js +Entrypoint another = vendors~another~index.bundle.js another.bundle.js +... +``` + +Here are some other useful plugins and loaders provided by the community for splitting code: + +- [`mini-css-extract-plugin`](/plugins/mini-css-extract-plugin): Useful for splitting CSS out from the main application. +- [`bundle-loader`](/loaders/bundle-loader): Used to split code and lazy load the resulting bundles. +- [`promise-loader`](https://github.com/gaearon/promise-loader): Similar to the `bundle-loader` but uses promises. + + +## Dynamic Imports + +Two similar techniques are supported by webpack when it comes to dynamic code splitting. The first and recommended approach is to use the [`import()` syntax](/api/module-methods#import-) that conforms to the [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) for dynamic imports. The legacy, webpack-specific approach is to use [`require.ensure`](/api/module-methods#require-ensure). Let's try using the first of these two approaches... + +W> `import()` calls use [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +Before we start, let's remove the extra [`entry`](/concepts/entry-points/) and [`optimization.splitChunks`](/plugins/split-chunks-plugin) from our config as they won't be needed for this next demonstration: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + mode: 'development', + entry: { ++ index: './src/index.js' +- index: './src/index.js', +- another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', ++ chunkFilename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- optimization: { +- splitChunks: { +- chunks: 'all' +- } +- } + }; +``` + +Note the use of `chunkFilename`, which determines the name of non-entry chunk files. For more information on `chunkFilename`, see [output documentation](/configuration/output/#output-chunkfilename). We'll also update our project to remove the now unused files: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +- |- another-module.js +|- /node_modules +``` + +Now, instead of statically importing `lodash`, we'll use dynamic importing to separate a chunk: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; +- +- function component() { ++ function getComponent() { +- var element = document.createElement('div'); +- +- // Lodash, now imported by this script +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => { ++ var element = document.createElement('div'); ++ ++ element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ ++ return element; ++ ++ }).catch(error => 'An error occurred while loading the component'); + } + +- document.body.appendChild(component()); ++ getComponent().then(component => { ++ document.body.appendChild(component); ++ }) +``` + +The reason we need `default` is since webpack 4, when importing a CommonJS module, the import will no longer resolve to the value of `module.exports`, it will instead create an artificial namespace object for the CommonJS module, for more information on the reason behind this, read [webpack 4: import() and CommonJs](https://medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655) + +Note the use of `webpackChunkName` in the comment. This will cause our separate bundle to be named `lodash.bundle.js` instead of just `[id].bundle.js`. For more information on `webpackChunkName` and the other available options, see the [`import()` documentation](/api/module-methods#import-). Let's run webpack to see `lodash` separated out to a separate bundle: + +``` bash +... + Asset Size Chunks Chunk Names + index.bundle.js 7.88 KiB index [emitted] index +vendors~lodash.bundle.js 547 KiB vendors~lodash [emitted] vendors~lodash +Entrypoint index = index.bundle.js +... +``` + +As `import()` returns a promise, it can be used with [`async` functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). However, this requires using a pre-processor like Babel and the [Syntax Dynamic Import Babel Plugin](https://babeljs.io/docs/plugins/syntax-dynamic-import/#installation). Here's how it would simplify the code: + +__src/index.js__ + +``` diff +- function getComponent() { ++ async function getComponent() { +- return import(/* webpackChunkName: "lodash" */ 'lodash').then({ default: _ } => { +- var element = document.createElement('div'); +- +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- +- return element; +- +- }).catch(error => 'An error occurred while loading the component'); ++ var element = document.createElement('div'); ++ const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash'); ++ ++ element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ ++ return element; + } + + getComponent().then(component => { + document.body.appendChild(component); + }); +``` + + +## Prefetching/Preloading modules + +webpack 4.6.0+ adds support for prefetching and preloading. + +Using these inline directives while declaring your imports allows webpack to output “Resource Hint” which tells the browser that for: + +- prefetch: resource is probably needed for some navigation in the future +- preload: resource might be needed during the current navigation + +Simple prefetch example can be having a `HomePage` component, which renders a `LoginButton` component which then on demand loads a `LoginModal` component after being clicked. + +__LoginButton.js__ + +```js +//... +import(/* webpackPrefetch: true */ 'LoginModal'); +``` + +This will result in `<link rel="prefetch" href="login-modal-chunk.js">` being appended in the head of the page, which will instruct the browser to prefetch in idle time the `login-modal-chunk.js` file. + +T> webpack will add the prefetch hint once the parent chunk has been loaded. + +Preload directive has a bunch of differences compared to prefetch: + +- A preloaded chunk starts loading in parallel to the parent chunk. A prefetched chunk starts after the parent chunk finishes loading. +- A preloaded chunk has medium priority and is instantly downloaded. A prefetched chunk is downloaded while browser is idle. +- A preloaded chunk should be instantly requested by the parent chunk. A prefetched chunk can be used anytime in the future. +- Browser support is different. + +Simple preload example can be having a `Component` which always depends on a big library that should be in a separate chunk. + +Let's imagine a component `ChartComponent` which needs huge `ChartingLibrary`. It displays a `LoadingIndicator` when rendered and instantly does an on demand import of `ChartingLibrary`: + +__ChartComponent.js__ + +```js +//... +import(/* webpackPreload: true */ 'ChartingLibrary'); +``` + +When a page which uses the `ChartComponent` is requested, the charting-library-chunk is also requested via `<link rel="preload">`. Assuming the page-chunk is smaller and finishes faster, the page will be displayed with a `LoadingIndicator`, until the already requested `charting-library-chunk` finishes. This will give a little load time boost since it only needs one round-trip instead of two. Especially in high-latency environments. + +T> Using webpackPreload incorrectly can actually hurt performance, so be careful when using it. + + +## Bundle Analysis + +Once you start splitting your code, it can be useful to analyze the output to check where modules have ended up. The [official analyze tool](https://github.com/webpack/analyse) is a good place to start. There are some other community-supported options out there as well: + +- [webpack-chart](https://alexkuz.github.io/webpack-chart/): Interactive pie chart for webpack stats. +- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/): Visualize and analyze your bundles to see which modules are taking up space and which might be duplicates. +- [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer): A plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap. +- [webpack bundle optimize helper](https://webpack.jakoblind.no/optimize): This tool will analyze your bundle and give you actionable suggestions on what to improve to reduce your bundle size. + +## Next Steps + +See [Lazy Loading](/guides/lazy-loading) for a more concrete example of how `import()` can be used in a real application and [Caching](/guides/caching) to learn how to split code more effectively. + + +# Lazy Loading + +T> This guide is a small follow-up to [Code Splitting](/guides/code-splitting). If you have not yet read through that guide, please do so now. + +Lazy, or "on demand", loading is a great way to optimize your site or application. This practice essentially involves splitting your code at logical breakpoints, and then loading it once the user has done something that requires, or will require, a new block of code. This speeds up the initial load of the application and lightens its overall weight as some blocks may never even be loaded. + + +## Example + +Let's take the example from [Code Splitting](/guides/code-splitting#dynamic-imports) and tweak it a bit to demonstrate this concept even more. The code there does cause a separate chunk, `lodash.bundle.js`, to be generated and technically "lazy-loads" it as soon as the script is run. The trouble is that no user interaction is required to load the bundle -- meaning that every time the page is loaded, the request will fire. This doesn't help us too much and will impact performance negatively. + +Let's try something different. We'll add an interaction to log some text to the console when the user clicks a button. However, we'll wait to load that code (`print.js`) until the interaction occurs for the first time. To do this we'll go back and rework the [final _Dynamic Imports_ example](/guides/code-splitting#dynamic-imports) from _Code Splitting_ and leave `lodash` in the main chunk. + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- print.js +|- /node_modules +``` + +__src/print.js__ + +``` js +console.log('The print.js module has loaded! See the network tab in dev tools...'); + +export default () => { + console.log('Button Clicked: Here\'s "some text"!'); +}; +``` + +__src/index.js__ + +``` diff ++ import _ from 'lodash'; ++ +- async function getComponent() { ++ function component() { + var element = document.createElement('div'); +- const _ = await import(/* webpackChunkName: "lodash" */ 'lodash'); ++ var button = document.createElement('button'); ++ var br = document.createElement('br'); + ++ button.innerHTML = 'Click me and look at the console!'; + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.appendChild(br); ++ element.appendChild(button); ++ ++ // Note that because a network request is involved, some indication ++ // of loading would need to be shown in a production-level site/app. ++ button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => { ++ var print = module.default; ++ ++ print(); ++ }); + + return element; + } + +- getComponent().then(component => { +- document.body.appendChild(component); +- }); ++ document.body.appendChild(component()); +``` + +W> Note that when using `import()` on ES6 modules you must reference the `.default` property as it's the actual `module` object that will be returned when the promise is resolved. + +Now let's run webpack and check out our new lazy-loading functionality: + +``` bash +... + Asset Size Chunks Chunk Names +print.bundle.js 417 bytes 0 [emitted] print +index.bundle.js 548 kB 1 [emitted] [big] index + index.html 189 bytes [emitted] +... +``` + + +## Frameworks + +Many frameworks and libraries have their own recommendations on how this should be accomplished within their methodologies. Here are a few examples: + +- React: [Code Splitting and Lazy Loading](https://reacttraining.com/react-router/web/guides/code-splitting) +- Vue: [Lazy Load in Vue using Webpack's code splitting](https://alexjoverm.github.io/2017/07/16/Lazy-load-in-Vue-using-Webpack-s-code-splitting/) +- AngularJS: [AngularJS + Webpack = lazyLoad](https://medium.com/@var_bin/angularjs-webpack-lazyload-bb7977f390dd) by [@var_bincom](https://twitter.com/var_bincom) + + +# Caching + +T> The examples in this guide stem from [getting started](/guides/getting-started), [output management](/guides/output-management) and [code splitting](/guides/code-splitting). + +So we're using webpack to bundle our modular application which yields a deployable `/dist` directory. Once the contents of `/dist` have been deployed to a server, clients (typically browsers) will hit that server to grab the site and its assets. The last step can be time consuming, which is why browsers use a technique called [caching](https://searchstorage.techtarget.com/definition/cache). This allows sites to load faster with less unnecessary network traffic, however it can also cause headaches when you need new code to be picked up. + +This guide focuses on the configuration needed to ensure files produced by webpack compilation can remain cached unless their contents has changed. + + +## Output Filenames + +A simple way to ensure the browser picks up changed files is by using `output.filename` [substitutions](/configuration/output#output-filename). The `[hash]` substitution can be used to include a build-specific hash in the filename, however it's even better to use the `[contenthash]` substitution which is the hash of the content of a file, which is different for each asset. + +Let's get our project set up using the example from [getting started](/guides/getting-started) with the `plugins` from [output management](/guides/output-management), so we don't have to deal with maintaining our `index.html` file manually: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +|- /node_modules +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ +- title: 'Output Management' ++ title: 'Caching' + }) + ], + output: { +- filename: 'bundle.js', ++ filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Running our build script, `npm run build`, with this configuration should produce the following output: + +``` bash +... + Asset Size Chunks Chunk Names +main.7e2c49a622975ebd9b7e.js 544 kB 0 [emitted] [big] main + index.html 197 bytes [emitted] +... +``` + +As you can see the bundle's name now reflects its content (via the hash). If we run another build without making any changes, we'd expect that filename to stay the same. However, if we were to run it again, we may find that this is not the case: + +``` bash +... + Asset Size Chunks Chunk Names +main.205199ab45963f6a62ec.js 544 kB 0 [emitted] [big] main + index.html 197 bytes [emitted] +... +``` + +This is because webpack includes certain boilerplate, specifically the runtime and manifest, in the entry chunk. + +W> Output may differ depending on your current webpack version. Newer versions may not have all the same issues with hashing as some older versions, but we still recommend the following steps to be safe. + +## Extracting Boilerplate + +As we learned in [code splitting](/guides/code-splitting), the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) can be used to split modules out into separate bundles. webpack provides an optimization feature which does split out runtime code into a separate chunk(s) according to the options provided, simply use [`optimization.runtimeChunk`](/configuration/optimization/#optimization-runtimechunk) set to `single` for creating one runtime bundle: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, ++ optimization: { ++ runtimeChunk: 'single' ++ } + }; +``` + +Let's run another build to see the extracted `runtime` bundle: + +``` bash +Hash: 82c9c385607b2150fab2 +Version: webpack 4.12.0 +Time: 3027ms + Asset Size Chunks Chunk Names +runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime + main.e81de2cf758ada72f306.js 69.5 KiB 1 [emitted] main + index.html 275 bytes [emitted] +[1] (webpack)/buildin/module.js 497 bytes {1} [built] +[2] (webpack)/buildin/global.js 489 bytes {1} [built] +[3] ./src/index.js 309 bytes {1} [built] + + 1 hidden module +``` + +It's also good practice to extract third-party libraries, such as `lodash` or `react`, to a separate `vendor` chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date. +This can be done by using the [`cacheGroups`](/plugins/split-chunks-plugin/#splitchunks-cachegroups) option of the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) demonstrated in [Example 2 of SplitChunksPlugin](/plugins/split-chunks-plugin/#split-chunks-example-2). Lets add `optimization.splitChunks` with `cacheGroups` with next params and build: + +__webpack.config.js__ + +``` diff + var path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + }), + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, + optimization: { +- runtimeChunk: 'single' ++ runtimeChunk: 'single', ++ splitChunks: { ++ cacheGroups: { ++ vendor: { ++ test: /[\\/]node_modules[\\/]/, ++ name: 'vendors', ++ chunks: 'all' ++ } ++ } ++ } + } + }; +``` + +Let's run another build to see our new `vendor` bundle: + +``` bash +... + Asset Size Chunks Chunk Names +runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime +vendors.a42c3ca0d742766d7a28.js 69.4 KiB 1 [emitted] vendors + main.abf44fedb7d11d4312d7.js 240 bytes 2 [emitted] main + index.html 353 bytes [emitted] +... +``` + +We can now see that our `main` bundle does not contain `vendor` code from `node_modules` directory and is down in size to `240 bytes`! + +## Module Identifiers + +Let's add another module, `print.js`, to our project: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- print.js +|- /node_modules +``` + +__print.js__ + +``` diff ++ export default function print(text) { ++ console.log(text); ++ }; +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import Print from './print'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.onclick = Print.bind(null, 'Hello webpack!'); + + return element; + } + + document.body.appendChild(component()); +``` + +Running another build, we would expect only our `main` bundle's hash to change, however... + +``` bash +... + Asset Size Chunks Chunk Names + vendor.a7561fb0e9a071baadb9.js 541 kB 0 [emitted] [big] vendor + main.b746e3eb72875af2caa9.js 1.22 kB 1 [emitted] main +manifest.1400d5af64fc1b7b3a45.js 5.85 kB 2 [emitted] manifest + index.html 352 bytes [emitted] +... +``` + +... we can see that all three have. This is because each [`module.id`](/api/module-variables#module-id-commonjs-) is incremented based on resolving order by default. Meaning when the order of resolving is changed, the IDs will be changed as well. So, to recap: + +- The `main` bundle changed because of its new content. +- The `vendor` bundle changed because its `module.id` was changed. +- And, the `manifest` bundle changed because it now contains a reference to a new module. + +The first and last are expected -- it's the `vendor` hash we want to fix. Luckily, there are two plugins we can use to resolve this issue. The first is the `NamedModulesPlugin`, which will use the path to the module rather than a numerical identifier. While this plugin is useful during development for more readable output, it does take a bit longer to run. The second option is the [`HashedModuleIdsPlugin`](/plugins/hashed-module-ids-plugin), which is recommended for production builds: + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const webpack = require('webpack'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + }), ++ new webpack.HashedModuleIdsPlugin() + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, + optimization: { + runtimeChunk: 'single', + splitChunks: { + cacheGroups: { + vendor: { + test: /[\\/]node_modules[\\/]/, + name: 'vendors', + chunks: 'all' + } + } + } + } + }; +``` + +Now, despite any new local dependencies, our `vendor` hash should stay consistent between builds: + +``` bash +... + Asset Size Chunks Chunk Names + main.216e852f60c8829c2289.js 340 bytes 0 [emitted] main +vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors +runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime + index.html 353 bytes [emitted] +Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.216e852f60c8829c2289.js +... +``` + +And let's modify our `src/index.js` to temporarily remove that extra dependency: + +__src/index.js__ + +``` diff + import _ from 'lodash'; +- import Print from './print'; ++ // import Print from './print'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- element.onclick = Print.bind(null, 'Hello webpack!'); ++ // element.onclick = Print.bind(null, 'Hello webpack!'); + + return element; + } + + document.body.appendChild(component()); +``` + +And finally run our build again: + +``` bash +... + Asset Size Chunks Chunk Names + main.ad717f2466ce655fff5c.js 274 bytes 0 [emitted] main +vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors +runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime + index.html 353 bytes [emitted] +Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.ad717f2466ce655fff5c.js +... +``` + +We can see that both builds yielded `55e79e5927a639d21a1b` in the `vendor` bundle's filename. + + +## Conclusion + +Caching gets messy. Plain and simple. However the walk-through above should give you a running start to deploying consistent, cacheable assets. See the _Further Reading_ section below to learn more. + + +# Authoring Libraries + +Aside from applications, webpack can also be used to bundle JavaScript libraries. The following guide is meant for library authors looking to streamline their bundling strategy. + + +## Authoring a Library + +Let's assume that you are writing a small library ,`webpack-numbers`, that allows users to convert the numbers 1 through 5 from their numeric representation to a textual one and vice-versa, e.g. 2 to 'two'. + +The basic project structure may look like this: + +__project__ + +``` diff ++ |- webpack.config.js ++ |- package.json ++ |- /src ++ |- index.js ++ |- ref.json +``` + +Initialize npm, install webpack and lodash: + +``` bash +npm init -y +npm install --save-dev webpack lodash +``` + +__src/ref.json__ + +```json +[ + { + "num": 1, + "word": "One" + }, + { + "num": 2, + "word": "Two" + }, + { + "num": 3, + "word": "Three" + }, + { + "num": 4, + "word": "Four" + }, + { + "num": 5, + "word": "Five" + }, + { + "num": 0, + "word": "Zero" + } +] +``` + +__src/index.js__ + +``` js +import _ from 'lodash'; +import numRef from './ref.json'; + +export function numToWord(num) { + return _.reduce(numRef, (accum, ref) => { + return ref.num === num ? ref.word : accum; + }, ''); +} + +export function wordToNum(word) { + return _.reduce(numRef, (accum, ref) => { + return ref.word === word && word.toLowerCase() ? ref.num : accum; + }, -1); +} +``` + +The usage specification for the library use will be as follows: + +- __ES2015 module import:__ + +``` js +import * as webpackNumbers from 'webpack-numbers'; +// ... +webpackNumbers.wordToNum('Two'); +``` + +- __CommonJS module require:__ + +``` js +var webpackNumbers = require('webpack-numbers'); +// ... +webpackNumbers.wordToNum('Two'); +``` + +- __AMD module require:__ + +``` js +require(['webpackNumbers'], function ( webpackNumbers) { + // ... + webpackNumbers.wordToNum('Two'); +}); +``` + +The consumer also can use the library by loading it via a script tag: + +``` html +<!doctype html> +<html> + ... + <script src="https://unpkg.com/webpack-numbers"></script> + <script> + // ... + // Global variable + webpackNumbers.wordToNum('Five') + // Property in the window object + window.webpackNumbers.wordToNum('Five') + // ... + </script> +</html> +``` + +Note that we can also configure it to expose the library in the following ways: + +- Property in the global object, for node. +- Property in the `this` object. + +For full library configuration and code please refer to [webpack-library-example](https://github.com/kalcifer/webpack-library-example). + + +## Base Configuration + +Now let's bundle this library in a way that will achieve the following goals: + +- Using `externals` to avoid bundling `lodash`, so the consumer is required to load it. +- Setting the library name as `webpack-numbers`. +- Exposing the library as a variable called `webpackNumbers`. +- Being able to access the library inside Node.js. + +Also, the consumer should be able to access the library the following ways: + +- ES2015 module. i.e. `import webpackNumbers from 'webpack-numbers'`. +- CommonJS module. i.e. `require('webpack-numbers')`. +- Global variable when included through `script` tag. + +We can start with this basic webpack configuration: + +__webpack.config.js__ + +``` js +var path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js' + } +}; +``` + + +## Externalize Lodash + +Now, if you run `webpack`, you will find that a largish bundle is created. If you inspect the file, you'll see that lodash has been bundled along with your code. In this case, we'd prefer to treat `lodash` as a `peerDependency`. Meaning that the consumer should already have `lodash` installed. Hence you would want to give up control of this external library to the consumer of your library. + +This can be done using the `externals` configuration: + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js' +- } ++ }, ++ externals: { ++ lodash: { ++ commonjs: 'lodash', ++ commonjs2: 'lodash', ++ amd: 'lodash', ++ root: '_' ++ } ++ } + }; +``` + +This means that your library expects a dependency named `lodash` to be available in the consumer's environment. + +T> Note that if you only plan on using your library as a dependency in another webpack bundle, you may specify `externals` as an array. + + +## External Limitations + +For libraries that use several files from a dependency: + +``` js +import A from 'library/one'; +import B from 'library/two'; + +// ... +``` + +You won't be able to exclude them from bundle by specifying `library` in the externals. You'll either need to exclude them one by one or by using a regular expression. + +``` js +module.exports = { + //... + externals: [ + 'library/one', + 'library/two', + // Everything that starts with "library/" + /^library\/.+$/ + ] +}; +``` + + +## Expose the Library + +For widespread use of the library, we would like it to be compatible in different environments, i.e. CommonJS, AMD, Node.js and as a global variable. To make your library available for consumption, add the `library` property inside `output`: + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), +- filename: 'webpack-numbers.js' ++ filename: 'webpack-numbers.js', ++ library: 'webpackNumbers' + }, + externals: { + lodash: { + commonjs: 'lodash', + commonjs2: 'lodash', + amd: 'lodash', + root: '_' + } + } + }; +``` + +T> Note that the `library` setup is tied to the `entry` configuration. For most libraries, specifying a single entry point is sufficient. While [multi-part libraries](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) are possible, it is simpler to expose partial exports through an [index script](https://stackoverflow.com/questions/34072598/es6-exporting-importing-in-index-file) that serves as a single entry point. Using an `array` as an `entry` point for a library is __not recommended__. + +This exposes your library bundle available as a global variable named `webpackNumbers` when imported. To make the library compatible with other environments, add `libraryTarget` property to the config. This will add the different options about how the library can be exposed. + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js', +- library: 'webpackNumbers' ++ library: 'webpackNumbers', ++ libraryTarget: 'umd' + }, + externals: { + lodash: { + commonjs: 'lodash', + commonjs2: 'lodash', + amd: 'lodash', + root: '_' + } + } + }; +``` + +You can expose the library in the following ways: + +- Variable: as a global variable made available by a `script` tag (`libraryTarget:'var'`). +- This: available through the `this` object (`libraryTarget:'this'`). +- Window: available trough the `window` object, in the browser (`libraryTarget:'window'`). +- UMD: available after AMD or CommonJS `require` (`libraryTarget:'umd'`). + +If `library` is set and `libraryTarget` is not, `libraryTarget` defaults to `var` as specified in the [output configuration documentation](/configuration/output). See [`output.libraryTarget`](/configuration/output#output-librarytarget) there for a detailed list of all available options. + +W> With webpack 3.5.5, using `libraryTarget: { root:'_' }` doesn't work properly (as stated in [issue 4824](https://github.com/webpack/webpack/issues/4824)). However, you can set `libraryTarget: { var: '_' }` to expect the library as a global variable. + + +### Final Steps + +Optimize your output for production by following the steps in the [production guide](/guides/production). Let's also add the path to your generated bundle as the package's `main` field in with our `package.json` + +__package.json__ + +``` json +{ + ... + "main": "dist/webpack-numbers.js", + ... +} +``` + +Or, to add as standard module as per [this guide](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage): + +``` json +{ + ... + "module": "src/index.js", + ... +} +``` + +The key `main` refers to the [standard from `package.json`](https://docs.npmjs.com/files/package.json#main), and `module` to [a](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md) [proposal](https://github.com/rollup/rollup/wiki/pkg.module) to allow the JavaScript ecosystem upgrade to use ES2015 modules without breaking backwards compatibility. + +W> The `module` property should point to a script that utilizes ES2015 module syntax but no other syntax features that aren't yet supported by browsers or node. This enables webpack to parse the module syntax itself, allowing for lighter bundles via [tree shaking](https://webpack.js.org/guides/tree-shaking/) if users are only consuming certain parts of the library. + +Now you can [publish it as an npm package](https://docs.npmjs.com/getting-started/publishing-npm-packages) and find it at [unpkg.com](https://unpkg.com/#/) to distribute it to your users. + +T> To expose stylesheets associated with your library, the [`ExtractTextPlugin`](/plugins/extract-text-webpack-plugin) should be used. Users can then consume and load these as they would any other stylesheet. + + +# Shimming + +The `webpack` compiler can understand modules written as ES2015 modules, CommonJS or AMD. However, some third party libraries may expect global dependencies (e.g. `$` for `jQuery`). The libraries might also create globals which need to be exported. These "broken modules" are one instance where _shimming_ comes into play. + +W> __We don't recommend using globals!__ The whole concept behind webpack is to allow more modular front-end development. This means writing isolated modules that are well contained and do not rely on hidden dependencies (e.g. globals). Please use these features only when necessary. + +Another instance where _shimming_ can be useful is when you want to [polyfill](https://en.wikipedia.org/wiki/Polyfill) browser functionality to support more users. In this case, you may only want to deliver those polyfills to the browsers that need patching (i.e. load them on demand). + +The following article will walk through both of these use cases. + +T> For simplicity, this guide stems from the examples in [Getting Started](/guides/getting-started). Please make sure you are familiar with the setup there before moving on. + + +## Shimming Globals + +Let's start with the first use case of shimming global variables. Before we do anything let's take another look at our project: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +|- /node_modules +``` + +Remember that `lodash` package we were using? For demonstration purposes, let's say we wanted to instead provide this as a global throughout our application. To do this, we can use the `ProvidePlugin`. + +The [`ProvidePlugin`](/plugins/provide-plugin) makes a package available as a variable in every module compiled through webpack. If webpack sees that variable used, it will include the given package in the final bundle. Let's go ahead by removing the `import` statement for `lodash` and instead providing it via the plugin: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; +- + function component() { + var element = document.createElement('div'); + +- // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') +- } ++ }, ++ plugins: [ ++ new webpack.ProvidePlugin({ ++ _: 'lodash' ++ }) ++ ] + }; +``` + +What we've essentially done here is tell webpack... + +> If you encounter at least one instance of the variable `_`, include the `lodash` package and provide it to the modules that need it. + +If we run a build, we should still see the same output: + +``` bash +... + Asset Size Chunks Chunk Names +bundle.js 544 kB 0 [emitted] [big] main +... +``` + +We can also use the `ProvidePlugin` to expose a single export of a module by configuring it with an "array path" (e.g. `[module, child, ...children?]`). So let's imagine we only wanted to provide the `join` method from `lodash` wherever it's invoked: + +__src/index.js__ + +``` diff + function component() { + var element = document.createElement('div'); + +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + plugins: [ + new webpack.ProvidePlugin({ +- _: 'lodash' ++ join: ['lodash', 'join'] + }) + ] + }; +``` + +This would go nicely with [Tree Shaking](/guides/tree-shaking) as the rest of the `lodash` library should get dropped. + + +## Granular Shimming + +Some legacy modules rely on `this` being the `window` object. Let's update our `index.js` so this is the case: + +``` diff + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); ++ ++ // Assume we are in the context of `window` ++ this.alert('Hmmm, this probably isn\'t a great idea...') + + return element; + } + + document.body.appendChild(component()); +``` + +This becomes a problem when the module is executed in a CommonJS context where `this` is equal to `module.exports`. In this case you can override `this` using the [`imports-loader`](/loaders/imports-loader/): + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ module: { ++ rules: [ ++ { ++ test: require.resolve('index.js'), ++ use: 'imports-loader?this=>window' ++ } ++ ] ++ }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + + +## Global Exports + +Let's say a library creates a global variable that it expects its consumers to use. We can add a small module to our setup to demonstrate this: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js ++ |- globals.js + |- /node_modules +``` + +__src/globals.js__ + +``` js +var file = 'blah.txt'; +var helpers = { + test: function() { console.log('test something'); }, + parse: function() { console.log('parse something'); } +}; +``` + +Now, while you'd likely never do this in your own source code, you may encounter a dated library you'd like to use that contains similar code to what's shown above. In this case, we can use [`exports-loader`](/loaders/exports-loader/), to export that global variable as a normal module export. For instance, in order to export `file` as `file` and `helpers.parse` as `parse`: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: require.resolve('index.js'), + use: 'imports-loader?this=>window' +- } ++ }, ++ { ++ test: require.resolve('globals.js'), ++ use: 'exports-loader?file,parse=helpers.parse' ++ } + ] + }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + +Now from within our entry script (i.e. `src/index.js`), we could `import { file, parse } from './globals.js';` and all should work smoothly. + + +## Loading Polyfills + +Almost everything we've discussed thus far has been in relation to handling legacy packages. Let's move on to our second topic: __polyfills__. + +There's a lot of ways to load polyfills. For example, to include the [`babel-polyfill`](https://babeljs.io/docs/usage/polyfill/) we might simply: + +``` bash +npm install --save babel-polyfill +``` + +and `import` it so as to include it in our main bundle: + +__src/index.js__ + +``` diff ++ import 'babel-polyfill'; ++ + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +T> Note that we aren't binding the `import` to a variable. This is because polyfills simply run on their own, prior to the rest of the code base, allowing us to then assume certain native functionality exists. + +Now while this is one approach, __including polyfills in the main bundle is not recommended__ because this penalizes modern browsers users by making them download a bigger file with unneeded scripts. + +Let's move our `import` to a new file and add the [`whatwg-fetch`](https://github.com/github/fetch) polyfill: + +``` bash +npm install --save whatwg-fetch +``` + +__src/index.js__ + +``` diff +- import 'babel-polyfill'; +- + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js + |- globals.js ++ |- polyfills.js + |- /node_modules +``` + +__src/polyfills.js__ + +```javascript +import 'babel-polyfill'; +import 'whatwg-fetch'; +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { +- entry: './src/index.js', ++ entry: { ++ polyfills: './src/polyfills.js', ++ index: './src/index.js' ++ }, + output: { +- filename: 'bundle.js', ++ filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: require.resolve('index.js'), + use: 'imports-loader?this=>window' + }, + { + test: require.resolve('globals.js'), + use: 'exports-loader?file,parse=helpers.parse' + } + ] + }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + +With that in place, we can add the logic to conditionally load our new `polyfills.bundle.js` file. How you make this decision depends on the technologies and browsers you need to support. We'll just do some simple testing to determine whether our polyfills are needed: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> + <title>Getting Started</title> ++ <script> ++ var modernBrowser = ( ++ 'fetch' in window && ++ 'assign' in Object ++ ); ++ ++ if ( !modernBrowser ) { ++ var scriptElement = document.createElement('script'); ++ ++ scriptElement.async = false; ++ scriptElement.src = '/polyfills.bundle.js'; ++ document.head.appendChild(scriptElement); ++ } ++ </script> + </head> + <body> + <script src="index.bundle.js"></script> + </body> + </html> +``` + +Now we can `fetch` some data within our entry script: + +__src/index.js__ + +``` diff + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); ++ ++ fetch('https://jsonplaceholder.typicode.com/users') ++ .then(response => response.json()) ++ .then(json => { ++ console.log('We retrieved some data! AND we\'re confident it will work on a variety of browser distributions.') ++ console.log(json) ++ }) ++ .catch(error => console.error('Something went wrong when fetching this data: ', error)) +``` + +If we run our build, another `polyfills.bundle.js` file will be emitted and everything should still run smoothly in the browser. Note that this set up could likely be improved upon but it should give you a good idea of how you can provide polyfills only to the users that actually need them. + + +## Further Optimizations + +The `babel-preset-env` package uses [browserslist](https://github.com/browserslist/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the [`useBuiltIns`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins) option, `false` by default, which converts your global `babel-polyfill` import to a more granular feature by feature `import` pattern: + +``` js +import 'core-js/modules/es7.string.pad-start'; +import 'core-js/modules/es7.string.pad-end'; +import 'core-js/modules/web.timers'; +import 'core-js/modules/web.immediate'; +import 'core-js/modules/web.dom.iterable'; +``` + +See [the repository](https://github.com/babel/babel-preset-env) for more information. + + +## Node Built-Ins + +Node built-ins, like `process`, can be polyfilled right directly from your configuration file without the use of any special loaders or plugins. See the [node configuration page](/configuration/node) for more information and examples. + + +## Other Utilities + +There are a few other tools that can help when dealing with legacy modules. + +The [`script-loader`](/loaders/script-loader/) evaluates code in the global context, similar to inclusion via a `script` tag. In this mode, every normal library should work. `require`, `module`, etc. are undefined. + +W> When using the `script-loader`, the module is added as a string to the bundle. It is not minimized by `webpack`, so use a minimized version. There is also no `devtool` support for libraries added by this loader. + +When there is no AMD/CommonJS version of the module and you want to include the `dist`, you can flag this module in [`noParse`](/configuration/module/#module-noparse). This will cause webpack to include the module without parsing it or resolving `require()` and `import` statements. This practice is also used to improve the build performance. + +W> Any feature requiring the AST, like the `ProvidePlugin`, will not work. + +Lastly, there are some modules that support multiple [module styles](/concepts/modules); e.g. a combination of AMD, CommonJS, and legacy. In most of these cases, they first check for `define` and then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by setting `define=>false` via the [`imports-loader`](/loaders/imports-loader/). + + +# Progressive Web Application + +T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. + +Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications. There are many things that can contribute to that. Of these, the most significant is the ability for an app to be able to function when __offline__. This is achieved through the use of a web technology called [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers/). + +This section will focus on adding an offline experience to our app. We'll achieve this using a Google project called [Workbox](https://github.com/GoogleChrome/workbox) which provides tools that help make offline support for web apps easier to setup. + + +## We Don't Work Offline Now + +So far, we've been viewing the output by going directly to the local file system. Typically though, a real user accesses a web app over a network; their browser talking to a __server__ which will serve up the required assets (e.g. `.html`, `.js`, and `.css` files). + +So let's test what the current experience is like using a simple server. Let's use the [http-server](https://www.npmjs.com/package/http-server) package: `npm install http-server --save-dev`. We'll also amend the `scripts` section of our `package.json` to add in a `start` script: + +__package.json__ + +``` diff +{ + ... + "scripts": { +- "build": "webpack" ++ "build": "webpack", ++ "start": "http-server dist" + }, + ... +} +``` + +If you haven't previously done so, run the command `npm run build` to build your project. Then run the command `npm start`. This should produce the following output: + +``` bash +> http-server dist + +Starting up http-server, serving dist +Available on: + http://xx.x.x.x:8080 + http://127.0.0.1:8080 + http://xxx.xxx.x.x:8080 +Hit CTRL-C to stop the server +``` + +If you open your browser to `http://localhost:8080` (i.e. `http://127.0.0.1`) you should see your webpack application being served from the `dist` directory. If you stop the server and refresh, the webpack application is no longer available. + +This is what we aim to change. Once we reach the end of this module we should be able to stop the server, hit refresh and still see our application. + + +## Adding Workbox + +Let's add the Workbox webpack plugin and adjust the `webpack.config.js` file: + +``` bash +npm install workbox-webpack-plugin --save-dev +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const WorkboxPlugin = require('workbox-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ +- title: 'Output Management' ++ title: 'Progressive Web Application' +- }) ++ }), ++ new WorkboxPlugin.GenerateSW({ ++ // these options encourage the ServiceWorkers to get in there fast ++ // and not allow any straggling "old" SWs to hang around ++ clientsClaim: true, ++ skipWaiting: true ++ }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +With that in place, let's see what happens when we do an `npm run build`: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 545 kB 0, 1 [emitted] [big] app + print.bundle.js 2.74 kB 1 [emitted] print + index.html 254 bytes [emitted] +precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 268 bytes [emitted] + service-worker.js 1 kB [emitted] +... +``` + +As you can see, we now have 2 extra files being generated; `service-worker.js` and the more verbose `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js`. `service-worker.js` is the Service Worker file and `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js` is a file that `service-worker.js` requires so it can run. Your own generated files will likely be different; but you should have an `service-worker.js` file there. + +So we're now at the happy point of having produced a Service Worker. What's next? + + +## Registering Our Service Worker + +Let's allow our Service Worker to come out and play by registering it. We'll do that by adding the registration code below: + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + ++ if ('serviceWorker' in navigator) { ++ window.addEventListener('load', () => { ++ navigator.serviceWorker.register('/service-worker.js').then(registration => { ++ console.log('SW registered: ', registration); ++ }).catch(registrationError => { ++ console.log('SW registration failed: ', registrationError); ++ }); ++ }); ++ } +``` + +Once more `npm run build` to build a version of the app including the registration code. Then serve it with `npm start`. Navigate to `http://localhost:8080` and take a look at the console. Somewhere in there you should see: + +``` bash +SW registered +``` + +Now to test it. Stop your server and refresh your page. If your browser supports Service Workers then you should still be looking at your application. However, it has been served up by your Service Worker and __not__ by the server. + + +## Conclusion + +You have built an offline app using the Workbox project. You've started the journey of turning your web app into a PWA. You may now want to think about taking things further. A good resource to help you with that can be found [here](https://developers.google.com/web/progressive-web-apps/). + + +# TypeScript + +T> This guide stems from the [_Getting Started_](/guides/getting-started/) guide. + +[TypeScript](https://www.typescriptlang.org) is a typed superset of JavaScript that compiles to plain JavaScript. In this guide we will learn how to integrate TypeScript with webpack. + + +## Basic Setup + +First install the TypeScript compiler and loader by running: + +``` bash +npm install --save-dev typescript ts-loader +``` + +Now we'll modify the directory structure & the configuration files: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- tsconfig.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src + |- index.js ++ |- index.ts + |- /node_modules +``` + +__tsconfig.json__ + +Let's set up a simple configuration to support JSX and compile TypeScript down to ES5... + +``` json +{ + "compilerOptions": { + "outDir": "./dist/", + "noImplicitAny": true, + "module": "es6", + "target": "es5", + "jsx": "react", + "allowJs": true + } +} +``` + +See [TypeScript's documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) to learn more about `tsconfig.json` configuration options. + +To learn more about webpack configuration, see the [configuration concepts](/concepts/configuration/). + +Now let's configure webpack to handle TypeScript: + +__webpack.config.js__ + +``` js +const path = require('path'); + +module.exports = { + entry: './src/index.ts', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [ '.tsx', '.ts', '.js' ] + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +This will direct webpack to _enter_ through `./index.ts`, _load_ all `.ts` and `.tsx` files through the `ts-loader`, and _output_ a `bundle.js` file in our current directory. + + +## Loader + +[`ts-loader`](https://github.com/TypeStrong/ts-loader) + +We use `ts-loader` in this guide as it makes enabling additional webpack features, such as importing other web assets, a bit easier. + + +## Source Maps + +To learn more about source maps, see the [development guide](/guides/development). + +To enable source maps, we must configure TypeScript to output inline source maps to our compiled JavaScript files. The following line must be added to our TypeScript configuration: + +__tsconfig.json__ + +``` diff + { + "compilerOptions": { + "outDir": "./dist/", ++ "sourceMap": true, + "noImplicitAny": true, + "module": "commonjs", + "target": "es5", + "jsx": "react", + "allowJs": true + } + } +``` + +Now we need to tell webpack to extract these source maps and include in our final bundle: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.ts', ++ devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [ '.tsx', '.ts', '.js' ] + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +See the [devtool documentation](/configuration/devtool/) for more information. + + +## Using Third Party Libraries + +When installing third party libraries from npm, it is important to remember to install the typing definition for that library. These definitions can be found at [TypeSearch](http://microsoft.github.io/TypeSearch/). + +For example if we want to install lodash we can run the following command to get the typings for it: + +``` bash +npm install --save-dev @types/lodash +``` + +For more information see [this blog post](https://blogs.msdn.microsoft.com/typescript/2016/06/15/the-future-of-declaration-files/). + + +## Importing Other Assets + +To use non-code assets with TypeScript, we need to defer the type for these imports. This requires a `custom.d.ts` file which signifies custom definitions for TypeScript in our project. Let's set up a declaration for `.svg` files: + +__custom.d.ts__ + +```typescript +declare module "*.svg" { + const content: any; + export default content; +} +``` + +Here we declare a new module for SVGs by specifying any import that ends in `.svg` and defining the module's `content` as `any`. We could be more explicit about it being a url by defining the type as string. The same concept applies to other assets including CSS, SCSS, JSON and more. + + +## Build Performance + +W> This may degrade build performance. + +See the [Build Performance](/guides/build-performance/) guide on build tooling. + + +# Environment Variables + +To disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production) you may use environment variables. + +The webpack command line [environment option](/api/cli/#environment-options) `--env` allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your `webpack.config.js`. For example, `--env.production` or `--env.NODE_ENV=local` (`NODE_ENV` is conventionally used to define the environment type, see [here](https://dzone.com/articles/what-you-should-know-about-node-env).) + +```bash +webpack --env.NODE_ENV=local --env.production --progress +``` + +T> Setting up your `env` variable without assignment, `--env.production` sets `--env.production` to `true` by default. There are also other syntaxes that you can use. See the [webpack CLI](/api/cli/#environment-options) documentation for more information. + +There is one change that you will have to make to your webpack config. Typically, `module.exports` points to the configuration object. To use the `env` variable, you must convert `module.exports` to a function: + +__webpack.config.js__ + +``` js +const path = require('path'); + +module.exports = env => { + // Use env.<YOUR VARIABLE> here: + console.log('NODE_ENV: ', env.NODE_ENV); // 'local' + console.log('Production: ', env.production); // true + + return { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +}; +``` + + +# Build Performance + +This guide contains some useful tips for improving build/compilation performance. + +--- + +## General + +The following best practices should help, whether you're running build scripts in [development](/guides/development) or [production](/guides/production). + + +### Stay Up to Date + +Use the latest webpack version. We are always making performance improvements. The latest stable version of webpack is: + +[](https://github.com/webpack/webpack/releases) + +Staying up-to-date with __Node.js__ can also help with performance. On top of this, keeping your package manager (e.g. `npm` or `yarn`) up-to-date can also help. Newer versions create more efficient module trees and increase resolving speed. + + +### Loaders + +Apply loaders to the minimal number of modules necessary. Instead of: + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + loader: 'babel-loader' + } + ] + } +}; +``` + +Use the `include` field to only apply the loader modules that actually need to be transformed by it: + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + include: path.resolve(__dirname, 'src'), + loader: 'babel-loader' + } + ] + } +}; +``` + + +### Bootstrap + +Each additional loader/plugin has a bootup time. Try to use as few tools as possible. + + +### Resolving + +The following steps can increase resolving speed: + +- Minimize the number of items in `resolve.modules`, `resolve.extensions`, `resolve.mainFiles`, `resolve.descriptionFiles`, as they increase the number of filesystem calls. +- Set `resolve.symlinks: false` if you don't use symlinks (e.g. `npm link` or `yarn link`). +- Set `resolve.cacheWithContext: false` if you use custom resolving plugins, that are not context specific. + + +### Dlls + +Use the `DllPlugin` to move code that is changed less often into a separate compilation. This will improve the application's compilation speed, although it does increase complexity of the build process. + + +### Smaller = Faster + +Decrease the total size of the compilation to increase build performance. Try to keep chunks small. + +- Use fewer/smaller libraries. +- Use the `CommonsChunkPlugin` in Multi-Page Applications. +- Use the `CommonsChunkPlugin` in `async` mode in Multi-Page Applications. +- Remove unused code. +- Only compile the part of the code you are currently developing on. + + +### Worker Pool + +The `thread-loader` can be used to offload expensive loaders to a worker pool. + +W> Don't use too many workers, as there is a boot overhead for the Node.js runtime and the loader. Minimize the module transfers between worker and main process. IPC is expensive. + + +### Persistent cache + +Enable persistent caching with the `cache-loader`. Clear cache directory on `"postinstall"` in `package.json`. + + +### Custom plugins/loaders + +Profile them to not introduce a performance problem here. + +--- + + +## Development + +The following steps are especially useful in _development_. + + +### Incremental Builds + +Use webpack's watch mode. Don't use other tools to watch your files and invoke webpack. The built-in watch mode will keep track of timestamps and passes this information to the compilation for cache invalidation. + +In some setups, watching falls back to polling mode. With many watched files, this can cause a lot of CPU load. In these cases, you can increase the polling interval with `watchOptions.poll`. + + +### Compile in Memory + +The following utilities improve performance by compiling and serving assets in memory rather than writing to disk: + +- `webpack-dev-server` +- `webpack-hot-middleware` +- `webpack-dev-middleware` + +### stats.toJson speed + +webpack 4 outputs a large amount of data with its `stats.toJson()` by default. Avoid retrieving portions of the `stats` object unless necessary in the incremental step. `webpack-dev-server` after v3.1.3 contained a substantial performance fix to minimize the amount of data retrieved from the `stats` object per incremental build step. + +### Devtool + +Be aware of the performance differences of the different `devtool` settings. + +- `"eval"` has the best performance, but doesn't assist you for transpiled code. +- The `cheap-source-map` variants are more performant, if you can live with the slightly worse mapping quality. +- Use a `eval-source-map` variant for incremental builds. + +=> In most cases, `cheap-module-eval-source-map` is the best option. + + +### Avoid Production Specific Tooling + +Certain utilities, plugins, and loaders only make sense when building for production. For example, it usually doesn't make sense to minify and mangle your code with the `TerserPlugin` while in development. These tools should typically be excluded in development: + +- `TerserPlugin` +- `ExtractTextPlugin` +- `[hash]`/`[chunkhash]` +- `AggressiveSplittingPlugin` +- `AggressiveMergingPlugin` +- `ModuleConcatenationPlugin` + + +### Minimal Entry Chunk + +webpack only emits updated chunks to the filesystem. For some configuration options, (HMR, `[name]`/`[chunkhash]` in `output.chunkFilename`, `[hash]`) the entry chunk is invalidated in addition to the changed chunks. + +Make sure the entry chunk is cheap to emit by keeping it small. The following code block extracts a chunk containing only the runtime with _all other chunks as children_: + +```js +new CommonsChunkPlugin({ + name: 'manifest', + minChunks: Infinity +}); +``` + +### Avoid Extra Optimization Steps + +webpack does extra algorithmic work to optimize the output for size and load performance. These optimizations are performant for smaller codebases, but can be costly in larger ones: + +```js +module.exports = { + // ... + optimization: { + removeAvailableModules: false, + removeEmptyChunks: false, + splitChunks: false, + } +}; +``` + +### Output Without Path Info + +webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Turn this off in the `options.output.pathinfo` setting: + +```js +module.exports = { + // ... + output: { + pathinfo: false + } +}; +``` + +### Node.js Version + +There has been a [performance regression](https://github.com/nodejs/node/issues/19769) in the latest stable versions of Node.js and its ES2015 `Map` and `Set` implementations. A fix has been merged into master, but a release has yet to be made. In the meantime, to get the most out of incremental build speeds, try to stick with version 8.9.x (the problem exists between 8.9.10 - 9.11.1). webpack has moved to using those ES2015 data structures liberally, and it will improve the initial build times as well. + +### TypeScript Loader + +Recently, `ts-loader` has started to consume the internal TypeScript watch mode APIs which dramatically decreases the number of modules to be rebuilt on each iteration. This `experimentalWatchApi` shares the same logic as the normal TypeScript watch mode itself and is quite stable for development use. Turn on `transpileOnly`, as well, for even faster incremental builds. + +```js +module.exports = { + // ... + test: /\.tsx?$/, + use: [ + { + loader: 'ts-loader', + options: { + transpileOnly: true, + experimentalWatchApi: true, + }, + }, + ], +}; +``` + +Note: the `ts-loader` documentation suggests the use of `cache-loader`, but this actually slows the incremental builds down with disk writes. + +To gain typechecking again, use the [`ForkTsCheckerWebpackPlugin`](https://www.npmjs.com/package/fork-ts-checker-webpack-plugin). + +There is a [full example](https://github.com/TypeStrong/ts-loader/tree/master/examples/fast-incremental-builds) on the ts-loader github repository. + +--- + + +## Production + +The following steps are especially useful in _production_. + +W> __Don't sacrifice the quality of your application for small performance gains!__ Keep in mind that optimization quality is, in most cases, more important than build performance. + + +### Multiple Compilations + +When using multiple compilations, the following tools can help: + +- [`parallel-webpack`](https://github.com/trivago/parallel-webpack): It allows for compilation in a worker pool. +- `cache-loader`: The cache can be shared between multiple compilations. + + +### Source Maps + +Source maps are really expensive. Do you really need them? + +--- + + +## Specific Tooling Issues + +The following tools have certain problems that can degrade build performance: + + +### Babel + +- Minimize the number of preset/plugins + + +### TypeScript + +- Use the `fork-ts-checker-webpack-plugin` for typechecking in a separate process. +- Configure loaders to skip typechecking. +- Use the `ts-loader` in `happyPackMode: true` / `transpileOnly: true`. + + +### Sass + +- `node-sass` has a bug which blocks threads from the Node.js thread pool. When using it with the `thread-loader` set `workerParallelJobs: 2`. + + +# Content Security Policies + +Webpack is capable of adding `nonce` to all scripts that it loads. To activate the feature set a `__webpack_nonce__` variable needs to be included in your entry script. A unique hash based nonce should be generated and provided for each unique page view this is why `__webpack_nonce__` is specified in the entry file and not in the configuration. Please note that `nonce` should always be a base64-encoded string. + + +## Examples + +In the entry file: + +``` js +// ... +__webpack_nonce__ = 'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM='; +// ... +``` + + +## Enabling CSP + +Please note that CSPs are not enabled by default. A corresponding header `Content-Security-Policy` or meta tag `<meta http-equiv="Content-Security-Policy" ...>` needs to be sent with the document to instruct the browser to enable the CSP. Here's an example of what a CSP header including a CDN white-listed URL might look like: + +``` http +Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; +``` + +For more information on CSP and `nonce` attribute, please refer to __Further Reading__ section at the bottom of this page. + + +# Development - Vagrant + +If you have a more advanced project and use [Vagrant](https://www.vagrantup.com/) to run your development environment in a Virtual Machine, you'll often want to also run webpack in the VM. + +## Configuring the Project + +To start, make sure that the `Vagrantfile` has a static IP; + +```ruby +Vagrant.configure("2") do |config| + config.vm.network :private_network, ip: "10.10.10.61" +end +``` + +Next, install webpack and webpack-dev-server in your project; + +```bash +npm install --save-dev webpack webpack-dev-server +``` + +Make sure to have a `webpack.config.js` file. If you haven't already, use this as a minimal example to get started: + +```js +module.exports = { + context: __dirname, + entry: './app.js' +}; +``` + +And create a `index.html` file. The script tag should point to your bundle. If `output.filename` is not specified in the config, this will be `bundle.js`. + +```html +<!doctype html> +<html> + <head> + <script src="/bundle.js" charset="utf-8"></script> + </head> + <body> + <h2>Heey!</h2> + </body> +</html> +``` + +Note that you also need to create an `app.js` file. + +## Running the Server + +Now, let's run the server: + +```bash +webpack-dev-server --host 0.0.0.0 --public 10.10.10.61:8080 --watch-poll +``` + +By default the server will only be accessible from localhost. We'll be accessing it from our host PC, so we need to change `--host` to allow this. + +webpack-dev-server will include a script in your bundle that connects to a WebSocket to reload when a change in any of your files occurs. +The `--public` flag makes sure the script knows where to look for the WebSocket. The server will use port `8080` by default, so we should also specify that here. + +`--watch-poll` makes sure that webpack can detect changes in your files. By default webpack listens to events triggered by the filesystem, but VirtualBox has many problems with this. + +The server should be accessible on `http://10.10.10.61:8080` now. If you make a change in `app.js`, it should live reload. + +## Advanced Usage with nginx + +To mimic a more production-like environment, it is also possible to proxy the webpack-dev-server with nginx. + +In your nginx config file, add the following: + +```nginx +server { + location / { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + error_page 502 @start-webpack-dev-server; + } + + location @start-webpack-dev-server { + default_type text/plain; + return 502 "Please start the webpack-dev-server first."; + } +} +``` + +The `proxy_set_header` lines are important, because they allow the WebSockets to work correctly. + +The command to start webpack-dev-server can then be changed to this: + +```bash +webpack-dev-server --public 10.10.10.61 --watch-poll +``` + +This makes the server only accessible on `127.0.0.1`, which is fine, because nginx takes care of making it available on your host PC. + +## Conclusion + +We made the Vagrant box accessible from a static IP, and then made webpack-dev-server publicly accessible so it is reachable from a browser. We then tackled a common problem that VirtualBox doesn't send out filesystem events, causing the server to not reload on file changes. + + +# Dependency Management + +> es6 modules + +> commonjs + +> amd + + +## require with expression + +A context is created if your request contains expressions, so the __exact__ module is not known on compile time. + +Example: + +```javascript +require('./template/' + name + '.ejs'); +``` + +webpack parses the `require()` call and extracts some information: + +```code +Directory: ./template +Regular expression: /^.*\.ejs$/ +``` + +__context module__ + +A context module is generated. It contains references to __all modules in that directory__ that can be required with a request matching the regular expression. The context module contains a map which translates requests to module ids. + +Example: + +```json +{ + "./table.ejs": 42, + "./table-row.ejs": 43, + "./directory/folder.ejs": 44 +} +``` + +The context module also contains some runtime logic to access the map. + +This means dynamic requires are supported but will cause all possible modules to be included in the bundle. + + +## `require.context` + +You can create your own context with the `require.context()` function. + +It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched +too, and a regular expression to match files against. + +webpack parses for `require.context()` in the code while building. + +The syntax is as follows: + +```javascript +require.context(directory, useSubdirectories = false, regExp = /^\.\//); +``` + +Examples: + +```javascript +require.context('./test', false, /\.test\.js$/); +// a context with files from the test directory that can be required with a request endings with `.test.js`. +``` + +```javascript +require.context('../', true, /\.stories\.js$/); +// a context with all files in the parent folder and descending folders ending with `.stories.js`. +``` + +W> The arguments passed to `require.context` must be literals! + + +### context module API + +A context module exports a (require) function that takes one argument: the request. + +The exported function has 3 properties: `resolve`, `keys`, `id`. + +- `resolve` is a function and returns the module id of the parsed request. +- `keys` is a function that returns an array of all possible requests that the context module can handle. + +This can be useful if you want to require all files in a directory or matching a pattern, Example: + +```javascript +function importAll (r) { + r.keys().forEach(r); +} + +importAll(require.context('../components/', true, /\.js$/)); +``` + +```javascript +var cache = {}; + +function importAll (r) { + r.keys().forEach(key => cache[key] = r(key)); +} + +importAll(require.context('../components/', true, /\.js$/)); +// At build-time cache will be populated with all required modules. +``` + +- `id` is the module id of the context module. This may be useful for `module.hot.accept`. + + +# Public Path + +The `publicPath` configuration option can be quite useful in a variety of scenarios. It allows you to specify the base path for all the assets within your application. + + +## Use Cases + +There are a few use cases in real applications where this feature becomes especially neat. Essentially, every file emitted to your `output.path` directory will be referenced from the `output.publicPath` location. This includes child chunks (created via [code splitting](/guides/code-splitting/)) and any other assets (e.g. images, fonts, etc.) that are a part of your dependency graph. + +### Environment Based + +In development for example, we might have an `assets/` folder that lives on the same level of our index page. This is fine, but what if we wanted to host all these static assets on a CDN in production? + +To approach this problem you can easily use a good old environment variable. Let's say we have a variable `ASSET_PATH`: + +``` js +import webpack from 'webpack'; + +// Try the environment variable, otherwise use root +const ASSET_PATH = process.env.ASSET_PATH || '/'; + +export default { + output: { + publicPath: ASSET_PATH + }, + + plugins: [ + // This makes it possible for us to safely use env vars on our code + new webpack.DefinePlugin({ + 'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH) + }) + ] +}; +``` + +### On The Fly + +Another possible use case is to set the `publicPath` on the fly. webpack exposes a global variable called `__webpack_public_path__` that allows you to do that. So, in your application's entry point, you can simply do this: + +```js +__webpack_public_path__ = process.env.ASSET_PATH; +``` + +That's all you need. Since we're already using the `DefinePlugin` on our +configuration, `process.env.ASSET_PATH` will always be defined so we can safely +do that. + +W> Be aware that if you use ES6 module imports in your entry file the `__webpack_public_path__` assignment will be done after the imports. In such cases, you'll have to move the public path assignment to its own dedicated module and then import it on top of your entry.js: + +```js +// entry.js +import './public-path'; +import './app'; +``` + + +# Integrations + +Let's start by clearing up a common misconception. webpack is a module bundler like [Browserify](http://browserify.org/) or [Brunch](http://brunch.io/). It is _not a task runner_ like [Make](https://www.gnu.org/software/make/), [Grunt](https://gruntjs.com/), or [Gulp](https://gulpjs.com/). Task runners handle automation of common development tasks such as linting, building, or testing your project. Compared to bundlers, task runners have a higher level focus. You can still benefit from their higher level tooling while leaving the problem of bundling to webpack. + +Bundlers help you get your JavaScript and stylesheets ready for deployment, transforming them into a format that's suitable for the browser. For example, JavaScript can be [minified](/plugins/terser-webpack-plugin) or [split into chunks](/guides/code-splitting) and [lazy-loaded](/guides/lazy-loading) to improve performance. Bundling is one of the most important challenges in web development, and solving it well can remove a lot of pain from the process. + +The good news is that, while there is some overlap, task runners and bundlers can play well together if approached in the right way. This guide provides a high-level overview of how webpack can be integrated into some of the more popular task runners. + + +## NPM Scripts + +Often webpack users use npm [`scripts`](https://docs.npmjs.com/misc/scripts) as their task runner. This is a good starting point. Cross-platform support can become a problem, but there are several workarounds for that. Many, if not most users, get by with simple npm `scripts` and various levels of webpack configuration and tooling. + +So while webpack's core focus is bundling, there are a variety of extensions that can enable you to use it for jobs typical of a task runner. Integrating a separate tool adds complexity, so be sure to weigh the pros and cons before going forward. + + +## Grunt + +For those using Grunt, we recommend the [`grunt-webpack`](https://www.npmjs.com/package/grunt-webpack) package. With `grunt-webpack` you can run webpack or [webpack-dev-server](https://github.com/webpack/webpack-dev-server) as a task, get access to stats within [template tags](https://gruntjs.com/api/grunt.template), split development and production configurations and more. Start by installing `grunt-webpack` as well as `webpack` itself if you haven't already: + +``` bash +npm install --save-dev grunt-webpack webpack +``` + +Then register a configuration and load the task: + +__Gruntfile.js__ + +``` js +const webpackConfig = require('./webpack.config.js'); + +module.exports = function(grunt) { + grunt.initConfig({ + webpack: { + options: { + stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development' + }, + prod: webpackConfig, + dev: Object.assign({ watch: true }, webpackConfig) + } + }); + + grunt.loadNpmTasks('grunt-webpack'); +}; +``` + +For more information, please visit the [repository](https://github.com/webpack-contrib/grunt-webpack). + + +## Gulp + +Gulp is also a fairly straightforward integration with the help of the [`webpack-stream`](https://github.com/shama/webpack-stream) package (a.k.a. `gulp-webpack`). In this case, it is unnecessary to install `webpack` separately as it is a direct dependency of `webpack-stream`: + +``` bash +npm install --save-dev webpack-stream +``` + +Just `require('webpack-stream')` instead of `webpack` and optionally pass it an configuration: + +__gulpfile.js__ + +``` js +var gulp = require('gulp'); +var webpack = require('webpack-stream'); +gulp.task('default', function() { + return gulp.src('src/entry.js') + .pipe(webpack({ + // Any configuration options... + })) + .pipe(gulp.dest('dist/')); +}); +``` + +For more information, please visit the [repository](https://github.com/shama/webpack-stream). + + +## Mocha + +The [`mocha-webpack`](https://github.com/zinserjan/mocha-webpack) utility can be used for a clean integration with Mocha. The repository offers more details on the pros and cons but essentially `mocha-webpack` is a simple wrapper that provides almost the same CLI as Mocha itself and provides various webpack functionality like an improved watch mode and improved path resolution. Here is a small example of how you would install it and use it to run a test suite (found within `./test`): + +``` bash +npm install --save-dev webpack mocha mocha-webpack +mocha-webpack 'test/**/*.js' +``` + +For more information, please visit the [repository](https://github.com/zinserjan/mocha-webpack). + + +## Karma + +The [`karma-webpack`](https://github.com/webpack-contrib/karma-webpack) package allows you to use webpack to pre-process files in [Karma](http://karma-runner.github.io/1.0/index.html). It also makes use of [`webpack-dev-middleware`](https://github.com/webpack/webpack-dev-middleware) and allows passing configurations for both. A simple example may look something like this: + +``` bash +npm install --save-dev webpack karma karma-webpack +``` + +__karma.conf.js__ + +``` js +module.exports = function(config) { + config.set({ + files: [ + { pattern: 'test/*_test.js', watched: false }, + { pattern: 'test/**/*_test.js', watched: false } + ], + preprocessors: { + 'test/*_test.js': [ 'webpack' ], + 'test/**/*_test.js': [ 'webpack' ] + }, + webpack: { + // Any custom webpack configuration... + }, + webpackMiddleware: { + // Any custom webpack-dev-middleware configuration... + } + }); +}; +``` + +For more information, please visit the [repository](https://github.com/webpack-contrib/karma-webpack). diff --git a/src/content/loaders/_loaders_all.md b/src/content/loaders/_loaders_all.md new file mode 100644 index 000000000000..a16e6814c65b --- /dev/null +++ b/src/content/loaders/_loaders_all.md @@ -0,0 +1,75 @@ + + +# Loaders + +webpack enables use of [loaders](/concepts/loaders) to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js. + +Loaders are activated by using `loadername!` prefixes in `require()` statements, or are automatically applied via regex from your webpack configuration – see [configuration](/concepts/loaders#configuration). + + +## Files + +- [`raw-loader`](/loaders/raw-loader) Loads raw content of a file (utf-8) +- [`val-loader`](/loaders/val-loader) Executes code as module and consider exports as JS code +- [`url-loader`](/loaders/url-loader) Works like the file loader, but can return a [data URL](https://tools.ietf.org/html/rfc2397) if the file is smaller than a limit +- [`file-loader`](/loaders/file-loader) Emits the file into the output folder and returns the (relative) URL +- [`ref-loader`](https://www.npmjs.com/package/ref-loader) Create dependencies between any files manually + + +## JSON + +- [`json-loader`](/loaders/json-loader) Loads a [JSON](http://json.org/) file (included by default) +- [`json5-loader`](/loaders/json5-loader) Loads and transpiles a [JSON 5](https://json5.org/) file +- [`cson-loader`](https://github.com/awnist/cson-loader) Loads and transpiles a [CSON](https://github.com/bevry/cson#what-is-cson) file + + +## Transpiling + +- [`script-loader`](/loaders/script-loader) Executes a JavaScript file once in global context (like in script tag), requires are not parsed +- [`babel-loader`](/loaders/babel-loader) Loads ES2015+ code and transpiles to ES5 using [Babel](https://babeljs.io/) +- [`buble-loader`](https://github.com/sairion/buble-loader) Loads ES2015+ code and transpiles to ES5 using [Bublé](https://buble.surge.sh/guide/) +- [`traceur-loader`](https://github.com/jupl/traceur-loader) Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler#readme) +- [`ts-loader`](https://github.com/TypeStrong/ts-loader) or [`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader) Loads [TypeScript](https://www.typescriptlang.org/) 2.0+ like JavaScript +- [`coffee-loader`](/loaders/coffee-loader) Loads [CoffeeScript](http://coffeescript.org/) like JavaScript +- [`fengari-loader`](https://github.com/fengari-lua/fengari-loader/) Loads Lua code using [fengari](https://fengari.io/) + + +## Templating + +- [`html-loader`](/loaders/html-loader) Exports HTML as string, require references to static resources +- [`pug-loader`](https://github.com/pugjs/pug-loader) Loads Pug and Jade templates and returns a function +- [`markdown-loader`](https://github.com/peerigon/markdown-loader) Compiles Markdown to HTML +- [`react-markdown-loader`](https://github.com/javiercf/react-markdown-loader) Compiles Markdown to a React Component using the markdown-parse parser +- [`posthtml-loader`](https://github.com/posthtml/posthtml-loader) Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) +- [`handlebars-loader`](https://github.com/pcardune/handlebars-loader) Compiles Handlebars to HTML +- [`markup-inline-loader`](https://github.com/asnowwolf/markup-inline-loader) Inline SVG/MathML files to HTML. It’s useful when applying icon font or applying CSS animation to SVG. +- [`twig-loader`](https://github.com/zimmo-be/twig-loader) Compiles Twig templates and returns a function + +## Styling + +- [`style-loader`](/loaders/style-loader) Add exports of a module as style to DOM +- [`css-loader`](/loaders/css-loader) Loads CSS file with resolved imports and returns CSS code +- [`less-loader`](/loaders/less-loader) Loads and compiles a LESS file +- [`sass-loader`](/loaders/sass-loader) Loads and compiles a SASS/SCSS file +- [`postcss-loader`](/loaders/postcss-loader) Loads and transforms a CSS/SSS file using [PostCSS](http://postcss.org) +- [`stylus-loader`](https://github.com/shama/stylus-loader) Loads and compiles a Stylus file + + +## Linting && Testing + +- [`mocha-loader`](/loaders/mocha-loader) Tests with [mocha](https://mochajs.org/) (Browser/NodeJS) +- [`eslint-loader`](https://github.com/webpack-contrib/eslint-loader) PreLoader for linting code using [ESLint](https://eslint.org/) +- [`jshint-loader`](/loaders/jshint-loader) PreLoader for linting code using [JSHint](http://jshint.com/about/) +- [`jscs-loader`](https://github.com/unindented/jscs-loader) PreLoader for code style checking using [JSCS](http://jscs.info/) +- [`coverjs-loader`](/loaders/coverjs-loader) PreLoader to determine the testing coverage using [CoverJS](https://github.com/arian/CoverJS) + + +## Frameworks + +- [`vue-loader`](https://github.com/vuejs/vue-loader) Loads and compiles [Vue Components](https://vuejs.org/v2/guide/components.html) +- [`polymer-loader`](https://github.com/webpack-contrib/polymer-webpack-loader) Process HTML & CSS with preprocessor of choice and `require()` Web Components like first-class modules +- [`angular2-template-loader`](https://github.com/TheLarkInn/angular2-template-loader) Loads and compiles [Angular](https://angular.io/) Components + + + +For more third-party loaders, see the list from [awesome-webpack](https://github.com/webpack-contrib/awesome-webpack#loaders). diff --git a/src/content/migrate/_migrate_all.md b/src/content/migrate/_migrate_all.md new file mode 100644 index 000000000000..c0c02cb9ff2b --- /dev/null +++ b/src/content/migrate/_migrate_all.md @@ -0,0 +1,786 @@ + + +# Migrate + +This section contains information about migrating from older versions of webpack to newer ones. + +# To v4 from v3 + +This guide only shows major changes that affect end users. For more details please see [the changelog](https://github.com/webpack/webpack/releases). + + +## Node.js v4 + +If you are still using Node.js v4 or lower, you need to upgrade your Node.js installation to Node.js v6 or higher. + + +## CLI + +The CLI has moved to a separate package: webpack-cli. You need to install it before using webpack, see [basic setup](/guides/getting-started/#basic-setup). + + +## Update plugins + +Many 3rd-party plugins need to be upgraded to their latest version to be compatible. + + +## mode + +Add the new [`mode`](/concepts/mode/) option to your config. Set it to production or development in your configuration depending on config type. + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + mode: 'production', +} +``` + +Alternatively you can pass it via CLI: `--mode production`/`--mode development` + +## Deprecated/Removed plugins + +These plugins can be removed from configuration as they are default in production mode: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NoEmitOnErrorsPlugin(), +- new ModuleConcatenationPlugin(), +- new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }) +- new UglifyJsPlugin() + ], +} +``` + +These plugins are default in development mode + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NamedModulesPlugin() + ], +} +``` + +These plugins were deprecated and are now removed: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NoErrorsPlugin(), +- new NewWatchingPlugin() + ], +} +``` + + +## CommonsChunkPlugin + +The `CommonsChunkPlugin` was removed. Instead the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) options can be used. + +See documentation of the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) for more details. The default configuration may already suit your needs. + +T> When generating the HTML from the stats you can use `optimization.splitChunks.chunks: "all"` which is the optimal configuration in most cases. + +## import() and CommonJS + +When using `import()` to load non-ESM the result has changed in webpack 4. Now you need to access the `default` property to get the value of `module.exports`. + +__non-esm.js__ + +``` javascript +module.exports = { + sayHello: () => { + console.log('hello world'); + } +}; +``` + +__example.js__ + +``` javascript +function sayHello() { + import('./non-esm.js').then(module => { + module.default.sayHello(); + }); +} +``` + +## json and loaders + +When using a custom loader to transform `.json` files you now need to change the module `type`: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + rules: [ + { + test: /config\.json$/, + loader: 'special-loader', ++ type: 'javascript/auto', + options: {...} + } + ] +}; +``` + +When still using the `json-loader`, it can be removed: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + rules: [ + { +- test: /\.json$/, +- loader: 'json-loader' + } + ] +}; +``` + +## module.loaders + +`module.loaders` were deprecated since webpack 2 and are now removed in favor of [`module.rules`](/configuration/module/#rule). + + +# To v2 or v3 from v1 + +The following sections describe the major changes from webpack 1 to 2. + +T> Note that there were far fewer changes between 2 and 3, so that migration shouldn't be too bad. If you are running into issues, please see [the changelog](https://github.com/webpack/webpack/releases) for details. + + +## `resolve.root`, `resolve.fallback`, `resolve.modulesDirectories` + +These options were replaced by a single option `resolve.modules`. See [resolving](/configuration/resolve) for more usage. + +``` diff + resolve: { +- root: path.join(__dirname, "src") ++ modules: [ ++ path.join(__dirname, "src"), ++ "node_modules" ++ ] + } +``` + + +## `resolve.extensions` + +This option no longer requires passing an empty string. This behavior was moved to `resolve.enforceExtension`. See [resolving](/configuration/resolve) for more usage. + + +## `resolve.*` + +Several APIs were changed here. Not listed in detail as it's not commonly used. See [resolving](/configuration/resolve) for details. + + +## `module.loaders` is now `module.rules` + +The old loader configuration was superseded by a more powerful rules system, which allows configuration of loaders and more. +For compatibility reasons, the old `module.loaders` syntax is still valid and the old names are parsed. +The new naming conventions are easier to understand and are a good reason to upgrade the configuration to using `module.rules`. + +``` diff + module: { +- loaders: [ ++ rules: [ + { + test: /\.css$/, +- loaders: [ +- "style-loader", +- "css-loader?modules=true" ++ use: [ ++ { ++ loader: "style-loader" ++ }, ++ { ++ loader: "css-loader", ++ options: { ++ modules: true ++ } ++ } + ] + }, + { + test: /\.jsx$/, + loader: "babel-loader", // Do not use "use" here + options: { + // ... + } + } + ] + } +``` + + +## Chaining loaders + +Like in webpack 1, loaders can be chained to pass results from loader to loader. Using the [rule.use](/configuration/module#rule-use) + configuration option, `use` can be set to an array of loaders. +In webpack 1, loaders were commonly chained with `!`. This style is only supported using the legacy option `module.loaders`. + +``` diff + module: { +- loaders: [{ ++ rules: [{ + test: /\.less$/, +- loader: "style-loader!css-loader!less-loader" ++ use: [ ++ "style-loader", ++ "css-loader", ++ "less-loader" ++ ] + }] + } +``` + + +## Automatic `-loader` module name extension removed + +It is not possible anymore to omit the `-loader` extension when referencing loaders: + +``` diff + module: { + rules: [ + { + use: [ +- "style", ++ "style-loader", +- "css", ++ "css-loader", +- "less", ++ "less-loader", + ] + } + ] + } +``` + +You can still opt-in to the old behavior with the `resolveLoader.moduleExtensions` configuration option, but this is not recommended. + +``` diff ++ resolveLoader: { ++ moduleExtensions: ["-loader"] ++ } +``` + +See [#2986](https://github.com/webpack/webpack/issues/2986) for the reason behind this change. + + +## `json-loader` is not required anymore + +When no loader has been configured for a JSON file, webpack will automatically try to load the JSON +file with the [`json-loader`](https://github.com/webpack-contrib/json-loader). + +``` diff + module: { + rules: [ +- { +- test: /\.json/, +- loader: "json-loader" +- } + ] + } +``` + +[We decided to do this](https://github.com/webpack/webpack/issues/3363) in order to iron out environment differences + between webpack, node.js and browserify. + + +## Loaders in configuration resolve relative to context + +In __webpack 1__, configured loaders resolve relative to the matched file. However, in __webpack 2__, configured loaders resolve relative to the `context` option. + +This solves some problems with duplicate modules caused by loaders when using `npm link` or referencing modules outside of the `context`. + +You may remove some hacks to work around this: + +``` diff + module: { + rules: [ + { + // ... +- loader: require.resolve("my-loader") ++ loader: "my-loader" + } + ] + }, + resolveLoader: { +- root: path.resolve(__dirname, "node_modules") + } +``` + + +## `module.preLoaders` and `module.postLoaders` were removed: + +``` diff + module: { +- preLoaders: [ ++ rules: [ + { + test: /\.js$/, ++ enforce: "pre", + loader: "eslint-loader" + } + ] + } +``` + + +## `UglifyJsPlugin` sourceMap + +The `sourceMap` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. This means that if you are using source maps for minimized code or want correct line numbers for uglifyjs warnings, you need to set `sourceMap: true` for `UglifyJsPlugin`. + +``` diff + devtool: "source-map", + plugins: [ + new UglifyJsPlugin({ ++ sourceMap: true + }) + ] +``` + + +## `UglifyJsPlugin` warnings + +The `compress.warnings` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. +This means that if you want to see uglifyjs warnings, you need to set `compress.warnings` to `true`. + +``` diff + devtool: "source-map", + plugins: [ + new UglifyJsPlugin({ ++ compress: { ++ warnings: true ++ } + }) + ] +``` + + +## `UglifyJsPlugin` minimize loaders + +`UglifyJsPlugin` no longer switches loaders into minimize mode. The `minimize: true` setting needs to be passed via loader options in the long-term. See loader documentation for relevant options. + +The minimize mode for loaders will be removed in webpack 3 or later. + +To keep compatibility with old loaders, loaders can be switched to minimize mode via plugin: + +``` diff + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ minimize: true ++ }) + ] +``` + + +## `DedupePlugin` has been removed + +`webpack.optimize.DedupePlugin` isn't needed anymore. Remove it from your configuration. + + +## `BannerPlugin` - breaking change + +`BannerPlugin` no longer accepts two parameters, but a single options object. + +``` diff + plugins: [ +- new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true}); ++ new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true}); + ] +``` + + +## `OccurrenceOrderPlugin` is now on by default + +The `OccurrenceOrderPlugin` is now enabled by default and has been renamed (`OccurenceOrderPlugin` in webpack 1). +Thus make sure to remove the plugin from your configuration: + +``` diff + plugins: [ + // webpack 1 +- new webpack.optimize.OccurenceOrderPlugin() + // webpack 2 +- new webpack.optimize.OccurrenceOrderPlugin() + ] +``` + + +## `ExtractTextWebpackPlugin` - breaking change + +[ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) requires version 2 to work with webpack 2. + +`npm install --save-dev extract-text-webpack-plugin` + +The configuration changes for this plugin are mainly syntactical. + +### `ExtractTextPlugin.extract` + +```diff +module: { + rules: [ + { + test: /.css$/, +- loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" }) ++ use: ExtractTextPlugin.extract({ ++ fallback: "style-loader", ++ use: "css-loader", ++ publicPath: "/dist" ++ }) + } + ] +} +``` + + +### `new ExtractTextPlugin({options})` + +```diff +plugins: [ +- new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false }) ++ new ExtractTextPlugin({ ++ filename: "bundle.css", ++ disable: false, ++ allChunks: true ++ }) +] +``` + + +## Full dynamic requires now fail by default + +A dependency with only an expression (i. e. `require(expr)`) will now create an empty context instead of the context of the complete directory. + +Code like this should be refactored as it won't work with ES2015 modules. If this is not possible you can use the `ContextReplacementPlugin` to hint the compiler towards the correct resolving. + +?> Link to an article about dynamic dependencies. + +### Using custom arguments in CLI and configuration + +If you abused the CLI to pass custom arguments to the configuration like so: + +`webpack --custom-stuff` + +```js +// webpack.config.js +var customStuff = process.argv.indexOf('--custom-stuff') >= 0; +/* ... */ +module.exports = config; +``` + +You may notice that this is no longer allowed. The CLI is more strict now. + +Instead there is an interface for passing arguments to the configuration. This should be used instead. Future tools may rely on this. + +`webpack --env.customStuff` + +```js +module.exports = function(env) { + var customStuff = env.customStuff; + /* ... */ + return config; +}; +``` + +See [CLI](/api/cli). + + +## `require.ensure` and AMD `require` are asynchronous + +These functions are now always asynchronous instead of calling their callback synchronously if the chunk is already loaded. + +__`require.ensure` now depends upon native `Promise`s. If using `require.ensure` in an environment that lacks them then you will need a polyfill.__ + + +## Loader configuration is through `options` + +You can _no longer_ configure a loader with a custom property in the `webpack.config.js`. It must be done through the `options`. The following configuration with the `ts` property is no longer valid with webpack 2: + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader' + }] + }, + // does not work with webpack 2 + ts: { transpileOnly: false } +}; +``` + + +### What are `options`? + +Good question. Well, strictly speaking it's 2 possible things; both ways to configure a webpack loader. Classically `options` was called `query` and was a string which could be appended to the name of the loader. Much like a query string but actually with [greater powers](https://github.com/webpack/loader-utils#parsequery): + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader?' + JSON.stringify({ transpileOnly: false }) + }] + } +}; +``` + +But it can also be a separately specified object that's supplied alongside a loader: + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader', + options: { transpileOnly: false } + }] + } +}; +``` + + +## `LoaderOptionsPlugin` context + +Some loaders need context information and read them from the configuration. This needs to be passed via loader options in the long-term. See loader documentation for relevant options. + +To keep compatibility with old loaders, this information can be passed via plugin: + +``` diff + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ options: { ++ context: __dirname ++ } ++ }) + ] +``` + + +## `debug` + +The `debug` option switched loaders to debug mode in webpack 1. This needs to be passed via loader options in long-term. See loader documentation for relevant options. + +The debug mode for loaders will be removed in webpack 3 or later. + +To keep compatibility with old loaders, loaders can be switched to debug mode via a plugin: + +``` diff +- debug: true, + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ debug: true ++ }) + ] +``` + + +## Code Splitting with ES2015 + +In webpack 1, you could use [`require.ensure()`](/api/module-methods#require-ensure) as a method to lazily-load chunks for your application: + +```javascript +require.ensure([], function(require) { + var foo = require('./module'); +}); +``` + +The ES2015 Loader spec defines [`import()`](/api/module-methods#import-) as method to load ES2015 Modules dynamically on runtime. webpack treats `import()` as a split-point and puts the requested module in a separate chunk. `import()` takes the module name as argument and returns a Promise. + +```js +function onClick() { + import('./module').then(module => { + return module.default; + }).catch(err => { + console.log('Chunk loading failed'); + }); +} +``` + +Good news: Failure to load a chunk can now be handled because they are `Promise` based. + + +## Dynamic expressions + +It's possible to pass a partial expression to `import()`. This is handled similar to expressions in CommonJS (webpack creates a [context](/plugins/context-replacement-plugin/) with all possible files). + +`import()` creates a separate chunk for each possible module. + +```js +function route(path, query) { + return import(`./routes/${path}/route`) + .then(route => new route.Route(query)); +} +// This creates a separate chunk for each possible route +``` + + +## Mixing ES2015 with AMD and CommonJS + +As for AMD and CommonJS you can freely mix all three module types (even within the same file). webpack behaves similar to babel and node-eps in this case: + +```javascript +// CommonJS consuming ES2015 Module +var book = require('./book'); + +book.currentPage; +book.readPage(); +book.default === 'This is a book'; +``` + +```javascript +// ES2015 Module consuming CommonJS +import fs from 'fs'; // module.exports map to default +import { readFileSync } from 'fs'; // named exports are read from returned object+ + +typeof fs.readFileSync === 'function'; +typeof readFileSync === 'function'; +``` + +It is important to note that you will want to tell Babel to not parse these module symbols so webpack can use them. You can do this by setting the following in your `.babelrc` or `babel-loader` options. + +__.babelrc__ + +```json +{ + "presets": [ + ["es2015", { "modules": false }] + ] +} +``` + + +## Hints + +No need to change something, but opportunities + +### Template strings + +webpack now supports template strings in expressions. This means you can start using them in webpack constructs: + +``` diff +- require("./templates/" + name); ++ require(`./templates/${name}`); +``` + + +### Configuration Promise + +webpack now supports returning a `Promise` from the configuration file. This allows async processing in your configuration file. + +__webpack.config.js__ + +```js +module.exports = function() { + return fetchLangs().then(lang => ({ + entry: '...', + // ... + plugins: [ + new DefinePlugin({ LANGUAGE: lang }) + ] + })); +}; +``` + + +### Advanced loader matching + +webpack now supports more things to match on for loaders. + +```js +module.exports = { + //... + module: { + rules: [ + { + resource: /filename/, // matches "/path/filename.js" + resourceQuery: /^\?querystring$/, // matches "?querystring" + issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js" + } + ] + } +}; +``` + + +### More CLI options + +There are some new CLI options for you to use: + +`--define process.env.NODE_ENV="production"` See [`DefinePlugin`](/plugins/define-plugin/). + +`--display-depth` displays the distance to the entry point for each module. + +`--display-used-exports` display info about which exports are used in a module. + +`--display-max-modules` sets the number for modules displayed in the output (defaults to 15). + +`-p` also defines `process.env.NODE_ENV` to `"production"` now. + + +## Loader changes + +Changes only relevant for loader authors. + + +### Cacheable + +Loaders are now cacheable by default. Loaders must opt-out if they are not cacheable. + +``` diff + // Cacheable loader + module.exports = function(source) { +- this.cacheable(); + return source; + } +``` + +``` diff + // Not cacheable loader + module.exports = function(source) { ++ this.cacheable(false); + return source; + } +``` + + +### Complex options + +__webpack 1__ only supports `JSON.stringify`-able options for loaders. + +__webpack 2__ now supports any JS object as loader options. + +Before webpack [2.2.1](https://github.com/webpack/webpack/releases/tag/v2.2.1) (i.e. from 2.0.0 through 2.2.0), using complex options required using `ident` for the `options` object to allow its reference from other loaders. __This was removed in 2.2.1__ and thus current migrations do not require any use of the `ident` key. + +```diff +{ + test: /\.ext/ + use: { + loader: '...', + options: { +- ident: 'id', + fn: () => require('./foo.js') + } + } +} +``` diff --git a/src/content/plugins/_plugins_all.md b/src/content/plugins/_plugins_all.md new file mode 100644 index 000000000000..65d63475ab80 --- /dev/null +++ b/src/content/plugins/_plugins_all.md @@ -0,0 +1,11 @@ + + +# MinChunkSizePlugin + +Keep chunk size above the specified limit by merging chunks that are smaller than the `minChunkSize`. + +``` js +new webpack.optimize.MinChunkSizePlugin({ + minChunkSize: 10000 // Minimum number of characters +}); +``` From c1e40becf8970d734915c3ef6409c39a6f39efa3 Mon Sep 17 00:00:00 2001 From: Axel D <SetTrend@users.noreply.github.com> Date: Sun, 13 Jan 2019 22:55:36 +0100 Subject: [PATCH 04/13] _all.md files removed, .gitigore amened to exclude _all.md files from being checked in. --- .gitignore | 1 + src/content/_all.md | 262 - src/content/api/_api_all.md | 3189 ---------- src/content/concepts/_concepts_all.md | 1086 ---- .../configuration/_configuration_all.md | 5315 ----------------- src/content/contribute/_contribute_all.md | 979 --- src/content/guides/_guides_all.md | 4880 --------------- src/content/loaders/_loaders_all.md | 75 - src/content/migrate/_migrate_all.md | 786 --- src/content/plugins/_plugins_all.md | 11 - 10 files changed, 1 insertion(+), 16583 deletions(-) delete mode 100644 src/content/_all.md delete mode 100644 src/content/api/_api_all.md delete mode 100644 src/content/concepts/_concepts_all.md delete mode 100644 src/content/configuration/_configuration_all.md delete mode 100644 src/content/contribute/_contribute_all.md delete mode 100644 src/content/guides/_guides_all.md delete mode 100644 src/content/loaders/_loaders_all.md delete mode 100644 src/content/migrate/_migrate_all.md delete mode 100644 src/content/plugins/_plugins_all.md diff --git a/.gitignore b/.gitignore index cbdc7c1002d9..7a30f590d9a6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ starter-kits-data.json .DS_Store yarn-error.log package-lock.json +src/content/**/*_all.md \ No newline at end of file diff --git a/src/content/_all.md b/src/content/_all.md deleted file mode 100644 index fb91d2979380..000000000000 --- a/src/content/_all.md +++ /dev/null @@ -1,262 +0,0 @@ - - -# Comparison - -webpack is not the only module bundler out there. If you are choosing between using webpack or any of the bundlers below, here is a feature-by-feature comparison on how webpack fares against the current competition. - -| Feature | webpack/webpack | jrburke/requirejs | substack/node-browserify | jspm/jspm-cli | rollup/rollup | brunch/brunch | -|---------|-----------------|-------------------|--------------------------|---------------|---------------|---------------| -| Additional chunks are loaded on demand | __yes__ | __yes__ | no | [System.import](https://github.com/systemjs/systemjs/blob/master/docs/system-api.md#systemimportmodulename--normalizedparentname---promisemodule) | no | no | -| AMD `define` | __yes__ | __yes__ | [deamdify](https://github.com/jaredhanson/deamdify) | yes | [rollup-plugin-amd](https://github.com/piuccio/rollup-plugin-amd) | yes | -| AMD `require` | __yes__ | __yes__ | no | yes | no | yes | -| AMD `require` loads on demand | __yes__ | with manual configuration | no | yes | no | no | -| CommonJS `exports` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | -| CommonJS `require` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | -| CommonJS `require.resolve` | __yes__ | no | no | no | no | | -| Concat in require `require("./fi" + "le")` | __yes__ | no♦ | no | no | no | | -| Debugging support | __SourceUrl, SourceMaps__ | not required | SourceMaps | __SourceUrl, SourceMaps__ | __SourceUrl, SourceMaps__ | SourceMaps | -| Dependencies | 19MB / 127 packages | 11MB / 118 packages | __1.2MB / 1 package__ | 26MB / 131 packages | ?MB / 3 packages | | -| ES2015 `import`/`export` | __yes__ (webpack 2) | no | no | __yes__ | __yes__ | yes, via [es6 module transpiler](https://github.com/gcollazo/es6-module-transpiler-brunch) -| Expressions in require (guided) `require("./templates/" + template)` | __yes (all files matching included)__ | no♦ | no | no | no | no | -| Expressions in require (free) `require(moduleName)` | with manual configuration | no♦ | no | no | no | | -| Generate a single bundle | __yes__ | yes♦ | yes | yes | yes | yes | -| Indirect require `var r = require; r("./file")` | __yes__ | no♦ | no | no | no | | -| Load each file separate | no | yes | no | yes | no | no | -| Mangle path names | __yes__ | no | partial | yes | not required (path names are not included in the bundle) | no | -| Minimizing | terser | uglify, closure compiler | [uglifyify](https://github.com/hughsk/uglifyify) | yes | [uglify-plugin](https://github.com/TrySound/rollup-plugin-uglify) | [UglifyJS-brunch](https://github.com/brunch/uglify-js-brunch) -| Multi pages build with common bundle | with manual configuration | __yes__ | with manual configuration | with bundle arithmetic | no | no| -| Multiple bundles | __yes__ | with manual configuration | with manual configuration | yes | no | yes | -| Node.js built-in libs `require("path")` | __yes__ | no | __yes__ | __yes__ | [node-resolve-plugin](https://github.com/rollup/rollup-plugin-node-resolve) | | -| Other Node.js stuff | process, __dir/filename, global | - | process, __dir/filename, global | process, __dir/filename, global for cjs | global ([commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs)) | | -| Plugins | __yes__ | yes | __yes__ | yes | yes | yes | -| Preprocessing | __loaders, [transforms](https://github.com/webpack-contrib/transform-loader)__ | loaders | transforms | plugin translate | plugin transforms | compilers, optimizers | -| Replacement for browser | `web_modules`, `.web.js`, package.json field, alias config option | alias option | package.json field, alias option | package.json, alias option | no | | -| Requirable files | file system | __web__ | file system | through plugins | file system or through plugins | file system | -| Runtime overhead | __243B + 20B per module + 4B per dependency__ | 14.7kB + 0B per module + (3B + X) per dependency | 415B + 25B per module + (6B + 2X) per dependency | 5.5kB for self-executing bundles, 38kB for full loader and polyfill, 0 plain modules, 293B CJS, 139B ES2015 System.register before gzip | __none for ES2015 modules__ (other formats may have) | | -| Watch mode | yes | not required | [watchify](https://github.com/browserify/watchify) | not needed in dev | [rollup-watch](https://github.com/rollup/rollup-watch) | yes | - -♦ in production mode (opposite in development mode) - -X is the length of the path string - - -## Bundling vs. Loading - -It's important to note some key differences between _loading_ and _bundling_ modules. A tool like [SystemJS](https://github.com/systemjs/systemjs), which can be found under the hood of [JSPM](https://github.com/jspm/jspm-cli), is used to load and transpile modules at runtime in the browser. This differs significantly from webpack, where modules are transpiled (through "loaders") and bundled before hitting the browser. - -Each method has its advantages and disadvantages. Loading and transpiling modules at runtime can add a lot of overhead for larger sites and applications comprised of many modules. For this reason, SystemJS makes more sense for smaller projects where fewer modules are required. However, this may change a bit as [HTTP/2](https://http2.github.io/) will improve the speed at which files can be transferred from server to client. Note that HTTP/2 doesn't change anything about _transpiling_ modules, which will always take longer when done client-side. - - -# Branding Guidelines - -Here you can find __webpack__ project brand guidelines, assets, and license. See our official [media repository](https://github.com/webpack/media) for more information and to find the [license](https://github.com/webpack/media/blob/master/LICENSE) that governs this work. Click any of the images to download them. - - -## The Name - -webpack should __always__ be written in lower-case letters, even at the beginning of a sentence. - - -## Logo - -The webpack logo should be placed on a white background with enough space around it like this: - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-white-bg.png" alt="webpack logo default with proper spacing on light background" /> - -[svg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.jpg) - -Just double the size of the inner dark blue cube to get an idea how much space the logo should have. - -For dark backgrounds, you can use the negative version of the logo: - -<div style="display: block; background: #111;"> - <img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-dark-bg.png" alt="webpack logo default with proper spacing on light background" /> -</div> - -[svg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.jpg) - -T> Please use the __icon + text__ whenever possible. - - -## Icon only - -__The icon is designed to be used in layout-constrained areas. As previously stated, please prefer icon + text.__ - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon.png" width="250" alt="icon example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon.jpg) - -Square-sized icon for bigger areas (like avatars or profile pictures): - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-big.png" width="250" alt="icon square big example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon-square-big.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-big.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-big.jpg) - -Square-sized icon for smaller areas (like favicons): - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-small.png" width="50" alt="icon square small example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon-square-small.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-small.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-small.jpg) - -T> For those of you following our guidelines and have gotten this far, we've made a special smaller size image used especially for custom emoji (like in a slack or gitter channel ;)) - -<img src="/assets/icon-square-small-slack.png" width="50" alt="icon square small example"> - - -## Font - -We use the beautiful [Geomanist Medium](http://atipofoundry.com/fonts/geomanist) font from the extremely talented folks at the [Atipo Foundry](http://atipofoundry.com/) who provide the entire font family at a 'pay what you want' model. - - -## Color Palette - -The following colors are used throughout the site in various combinations and on our fancy clothing line launched with the help of [Open Collective](https://opencollective.com/) and [Threadless](https://medium.com/u/840563ee2a56) over at the [official webpack store](https://webpack.threadless.com/collections/the-final-release-collection/)! - -| Color Name | HEX Code | RGB Code | Sample -|---------------|---------------|-----------------------|------------------------------- -| Malibu: | HEX `#8dd6f9` | `rgb: 141, 214, 249` | <div style="background-color: #8dd6f9;"> </div> -| Denim: | HEX `#1d78c1` | `rgb: 29, 120, 193` | <div style="background-color: #1d78c1;"> </div> -| Fiord: | HEX `#465E69` | `rgb: 70, 94, 105` | <div style="background-color: #465E69;"> </div> -| Outer Space: | HEX `#2B3A42` | `rgb: 43, 58, 66` | <div style="background-color: #2B3A42;"> </div> -| White: | HEX `#ffffff` | `rgb: 255, 255, 255` | <div style="background-color: #ffffff;"> </div> -| Concrete: | HEX `#f2f2f2` | `rgb: 242, 242, 242` | <div style="background-color: #f2f2f2;"> </div> -| Alto: | HEX `#dedede` | `rgb: 222, 222, 222` | <div style="background-color: #dedede;"> </div> -| Dusty Gray: | HEX `#999999` | `rgb: 153, 153, 153` | <div style="background-color: #999999;"> </div> -| Dove Gray: | HEX `#666666` | `rgb: 102, 102, 102` | <div style="background-color: #666666;"> </div> -| Emperor: | HEX `#535353` | `rgb: 83, 83, 83` | <div style="background-color: #535353;"> </div> -| Mine Shaft: | HEX `#333333` | `rgb: 51, 51, 51` | <div style="background-color: #333333;"> </div> - -In addition, you can grab the following file types directly from these links: - -[psd](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.psd) | [png](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.png) - | [ai](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.ai) | [svg](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.svg) - - -## License - -The logo and the brand name are __not MIT licensed__. Please check [our LICENSE](https://github.com/webpack/media/blob/master/LICENSE) for usage guidelines. - - -# Glossary - -This index lists common terms used throughout the webpack ecosystem. - - -## A - -- [__Asset__](/guides/asset-management/): This a general term for the images, fonts, media, and any other kind of files that are typically used in websites and other applications. These typically end up as individual files within the [output](/glossary#o) but can also be inlined via things like the [style-loader](/loaders/style-loader) or [url-loader](/loaders/url-loader). - - -## B - -- [__Bundle__](/guides/getting-started/#creating-a-bundle): Produced from a number of distinct modules, bundles contain the final versions of source files that have already undergone the loading and compilation process. -- [__Bundle Splitting__](/guides/code-splitting): This process offers one way of optimizing a build, allowing webpack to generate multiple bundles for a single application. As a result, each bundle can be isolated from changes effecting others, reducing the amount of code that needs to be republished and therefore re-downloaded by the client and taking advantage of browser caching. - - -## C - -- __Chunk__: This webpack-specific term is used internally to manage the bundling process. Bundles are composed out of chunks, of which there are several types (e.g. entry and child). Typically, _chunks_ directly correspond with the output _bundles_ however, there are some configurations that don't yield a one-to-one relationship. -- [__Code Splitting__](/guides/code-splitting/): Refers to dividing your code into various bundles/chunks which you can then load on demand instead of loading a single bundle containing everything. -- [__Configuration__](/concepts/configuration/): webpack config file is a plain old JavaScript file that exports an object. This object is then processed by webpack based upon its defined properties. - - -## D - -- [__Dependency Graph__](/concepts/dependency-graph): Any time one file depends on another, webpack treats this as a _dependency_. Starting from an entry point(s), webpack recursively builds a dependency graph that includes every module/asset your application needs. - - -## E - -- [__Entry Point__](/concepts/entry-points): The entry point tells webpack where to start and follows the graph of dependencies to know what to bundle. You can think of your application's entry point(s) as the __contextual root(s)__ of what you want bundled. - - -## F - -## G - -## H - -- [__Hot Module Replacement (HMR)__](/concepts/hot-module-replacement): A process that exchanges, adds, or removes `modules` while an application is running without a full page reload. - - -## I - -## J - -## K - -## L - -- [__Loaders__](/concepts/loaders): Transformations that are applied on the source code of a module. They allow you to pre-process files as you `require()` or "load" them. Similar to a 'task-runner'. - - -## M - -- [__Module__](/concepts/modules): Discrete chunks of functionality that provide a smaller surface area than a full program. Well-written modules provide solid abstractions and encapsulation boundaries which make up a coherent design and clear purpose. -- [__Module Resolution__](/concepts/module-resolution/): A module can be required as a dependency from another module and a resolver is a library which helps in locating a module by its absolute path.. Modules are searched for inside all directories specified in `resolve.modules`. - - -## N - -## O - -- [__Output__](/concepts/output): Option(s) specifying where to output the compiled files to disk. - > _Note, that while there can be multiple entry points, only one output configuration is specified._ - - -## P - -- [__Plugin__](/concepts/plugins): A JavaScript object that has an `apply` property. This `apply` property is called by the webpack compiler, giving access to the entire compilation lifecycle. These packages will typically extend compilation functionality in one way or another. - - -## Q - -## R - -- [__Request__](/guides/dependency-management/): Refers to the expression in the require/import statement, e.g. _require("./template/" + name + ".ejs")_, the request is _"./template/" + name + ".ejs"_. - -## S - -## T - -- [__Target__](/configuration/target/): User configured deployment target(s) [listed here](/configuration/target/) to compile for a specific environment like the browser, NodeJS, or Electron. -- [__Tree Shaking__](/guides/tree-shaking/): Unused/Excess code elimination, or more precisely, live code importing. Compilers like webpack will accomplish this by analyzing the various kinds `import` statements and usage of the imported code to determine what parts of dependencies are actually being utilized, dropping parts of the "tree" that are not. - - -## U - -## V - -- [__Vendor Entry Point__](/concepts/entry-points/#separate-app-and-vendor-entries): Create dependency graphs starting at both `app.js` and `vendors.js`. These graphs are completely separate and independent of each other to allow leverage of `CommonsChunkPlugin` and extract any vendor references from your app bundle into your vendor bundle. Helps achieve a common pattern in webpack known as [long-term vendor-caching](/guides/caching/). - - -## W - -- [__webpack__](/): A highly configurable [module](/concepts/modules) bundler for modern JavaScript applications - - -## X - -## Y - -## Z - - -# License - -## webpack - -webpack is [MIT licensed](https://github.com/webpack/webpack/blob/master/LICENSE). - -## webpack logo and icon - -The webpack logo and icon are under a different license which can be -found [here](https://github.com/webpack/media). - -## webpack documentation - -The content on [https://webpack.js.org/](https://webpack.js.org/) is available under [Creative Commons BY 4.0](https://creativecommons.org/licenses/by/4.0/) license meaning attribution is required should you use the content elsewhere. - -## webpack code samples - -The code samples use [CC0 1.0 Universal (CC0 1.0) (Public Domain)](https://creativecommons.org/publicdomain/zero/1.0/) and you are free to use them as you like. diff --git a/src/content/api/_api_all.md b/src/content/api/_api_all.md deleted file mode 100644 index d54e6da2b86f..000000000000 --- a/src/content/api/_api_all.md +++ /dev/null @@ -1,3189 +0,0 @@ - - -# Compiler Hooks - -The `Compiler` module is the main engine that creates a compilation instance -with all the options passed through the [CLI](/api/cli) or [Node API](/api/node). It extends the -`Tapable` class in order to register and call plugins. Most user facing plugins -are first registered on the `Compiler`. - -T> This module is exposed as `webpack.Compiler` and can be used directly. See -[this example](https://github.com/pksjce/webpack-internal-examples/tree/master/compiler-example) -for more information. - -When developing a plugin for webpack, you might want to know where each hook is called. To learn this, search for `hooks.<hook name>.call` across the webpack source - - -## Watching - -The `Compiler` supports [watching](/api/node/#watching) which monitors the file -system and recompiles as files change. When in watch mode, the compiler will -emit the additional events such as `watchRun`, `watchClose`, and `invalid`. -This is typically used in [development](/guides/development), usually under -the hood of tools like `webpack-dev-server`, so that the developer doesn't -need to re-compile manually every time. Watch mode can also be entered via the -[CLI](/api/cli/#watch-options). - - -## Hooks - -The following lifecycle hooks are exposed by the `compiler` and can be accessed -as such: - -``` js -compiler.hooks.someHook.tap(/* ... */); -``` - -Depending on the hook type, `tapAsync` and `tapPromise` may also be available. - -For the description of hook types, see [the Tapable docs](https://github.com/webpack/tapable#hook-types). - - -### `entryOption` - -`SyncBailHook` - -Executes a plugin after [the `entry` configuration](https://webpack.js.org/configuration/entry-context/#entry) from webpack options has been processed. - - -### `afterPlugins` - -`SyncHook` - -Runs a plugin after setting up initial set of plugins. - -Parameters: `compiler` - - -### `afterResolvers` - -`SyncHook` - -Executes a plugin after resolver setup is complete. - -Parameters: `compiler` - - -### `environment` - -`SyncHook` - -Runs a plugin before the environment is prepared. - - -### `afterEnvironment` - -`SyncHook` - -Executes a plugin a environment setup is complete. - - -### `beforeRun` - -`AsyncSeriesHook` - -Adds a hook right before `compiler.run()` is executed. - -Parameters: `compiler` - - -### `run` - -`AsyncSeriesHook` - -Hook into the compiler before it begins reading records. - -Parameters: `compiler` - - -### `watchRun` - -`AsyncSeriesHook` - -Executes a plugin during watch mode after a new compilation is triggered -but before the compilation is actually started. - -Parameters: `compiler` - - -### `normalModuleFactory` - -`SyncHook` - -Runs a plugin after a `NormalModuleFactory` is created. - -Parameters: `normalModuleFactory` - - -### `contextModuleFactory` - -Runs a plugin after a `ContextModuleFactory` is created. - -Parameters: `contextModuleFactory` - - -### `beforeCompile` - -`AsyncSeriesHook` - -Executes a plugin after compilation parameters are created. - -Parameters: `compilationParams` - - -### `compile` - -`SyncHook` - -Hook into the compiler before a new compilation is created. - -Parameters: `compilationParams` - - -### `thisCompilation` - -`SyncHook` - -Executed before emitting the `compilation` event (see below). - -Parameters: `compilation` - - -### `compilation` - -`SyncHook` - -Runs a plugin after a compilation has been created. - -Parameters: `compilation` - - -### `make` - -`AsyncParallelHook` - -... - -Parameters: `compilation` - - -### `afterCompile` - -`AsyncSeriesHook` - -... - -Parameters: `compilation` - - -### `shouldEmit` - -`SyncBailHook` - -Can return true/false at this point - -Parameters: `compilation` - - -### `emit` - -`AsyncSeriesHook` - -Before emitting assets to output dir - -Parameters: `compilation` - - -### `afterEmit` - -`AsyncSeriesHook` - -After emitting assets to output dir - -Parameters: `compilation` - - -### `done` - -`AsyncSeriesHook` - -Compilation has completed. - -Parameters: `stats` - - -### `failed` - -`SyncHook` - -Compilation has failed. - -Parameters: `error` - - -### `invalid` - -`SyncHook` - -Watch compilation has been invalidated. - -Parameters: `fileName`, `changeTime` - - -### `watchClose` - -`SyncHook` - -Watch mode has stopped. - - -# Introduction - -A variety of interfaces are available to customize the compilation process. -Some features overlap between interfaces, e.g. a configuration option may be -available via a CLI flag, while others exist only through a single interface. -The following high-level information should get you started. - - -## CLI - -The Command Line Interface (CLI) to configure and interact with your build. It -is especially useful in the case of early prototyping and profiling. For the -most part, the CLI is simply used to kick off the process using a configuration -file and a few flags (e.g. `--env`). - -[Learn more about the CLI!](/api/cli) - - -## Module - -When processing modules with webpack, it is important to understand the -different module syntaxes -- specifically the [methods](/api/module-methods) -and [variables](/api/module-variables) -- that are supported. - -[Learn more about modules!](/api/module-methods) - - -## Node - -While most users can get away with just using the CLI along with a -configuration file, more fine-grained control of the compilation can be -achieved via the Node interface. This includes passing multiple configurations, -programmatically running or watching, and collecting stats. - -[Learn more about the Node API!](/api/node) - - -## Loaders - -Loaders are transformations that are applied to the source code of a module. -They are written as functions that accept source code as a parameter and return -a new version of that code with transformations applied. - -[Learn more about loaders!](/api/loaders) - - -## Plugins - -The plugin interface allows users to tap directly into the compilation process. -Plugins can register handlers on lifecycle hooks that run at different points -throughout a compilation. When each hook is executed, the plugin will have full -access to the current state of the compilation. - -[Learn more about plugins!](/api/plugins) - - -# Command Line Interface - -For proper usage and easy distribution of this configuration, webpack can be configured with `webpack.config.js`. Any parameters sent to the CLI will map to a corresponding parameter in the config file. - -Read the [installation guide](/guides/installation) if you don't already have webpack and CLI installed. - - -## Usage with config file - -```sh -webpack [--config webpack.config.js] -``` - -See [configuration](/configuration) for the options in the configuration file. - - -## Usage without config file - -```sh -webpack <entry> [<entry>] -o <output> -``` - -__`<entry>`__ - -A filename or a set of named filenames which act as the entry point to build your project. You can pass multiple entries (every entry is loaded on startup). If you pass a pair in the form `<name>=<request>` you can create an additional entry point. It will be mapped to the configuration option `entry`. - -__`<output>`__ - -A path and filename for the bundled file to be saved in. It will be mapped to the configuration options `output.path` and `output.filename`. - -__Example__ - -If your project structure is as follows - - -```bash -. -├── dist -├── index.html -└── src - ├── index.js - ├── index2.js - └── others.js -``` - -```bash -webpack src/index.js -o dist/bundle.js -``` - -This will bundle your source code with entry as `index.js` and the output bundle file will have a path of `dist` and the filename will be `bundle.js` - -```bash - | Asset | Size | Chunks | Chunk Names | - |-----------|---------|-------------|-------------| - | bundle.js | 1.54 kB | 0 [emitted] | index | - [0] ./src/index.js 51 bytes {0} [built] - [1] ./src/others.js 29 bytes {0} [built] -``` - -```bash -webpack index=./src/index.js entry2=./src/index2.js dist/bundle.js -``` - -This will form the bundle with both the files as separate entry points. - -```bash - | Asset | Size | Chunks | Chunk Names | - |-----------|---------|---------------|---------------| - | bundle.js | 1.55 kB | 0,1 [emitted] | index, entry2 | - [0] ./src/index.js 51 bytes {0} [built] - [0] ./src/index2.js 54 bytes {1} [built] - [1] ./src/others.js 29 bytes {0} {1} [built] -``` - - -### Common Options - -W> Note that Command Line Interface has a higher precedence for the arguments you use it with than your configuration file. For instance, if you pass [`--mode="production"`](/concepts/mode/#usage) to webpack CLI and your configuration file uses `development`, `production` will be used. - -__List all of the options available on the cli__ - -```bash -webpack --help -webpack -h -``` - -__Build source using a config file__ - -Specifies a different [configuration](/configuration) file to pick up. Use this if you want to specify something different than `webpack.config.js`, which is the default. - -```bash -webpack --config example.config.js -``` - -__Print result of webpack as a JSON__ - -```bash -webpack --json -webpack --json > stats.json -``` - -In every other case, webpack prints out a set of stats showing bundle, chunk and timing details. Using this option the output can be a JSON object. This response is accepted by webpack's [analyse tool](https://webpack.github.io/analyse/), or chrisbateman's [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/), or th0r's [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). The analyse tool will take in the JSON and provide all the details of the build in graphical form. - -### Environment Options - -When the webpack configuration [exports a function](/configuration/configuration-types#exporting-a-function), an "environment" may be passed to it. - -```bash -webpack --env.production # sets env.production == true -webpack --env.platform=web # sets env.platform == "web" -``` - -The `--env` argument accepts various syntaxes: - -Invocation | Resulting environment ----------------------------------------- | --------------------------- -`webpack --env prod` | `"prod"` -`webpack --env.prod` | `{ prod: true }` -`webpack --env.prod=1` | `{ prod: 1 }` -`webpack --env.prod=foo` | `{ prod: "foo" }` -`webpack --env.prod --env.min` | `{ prod: true, min: true }` -`webpack --env.prod --env min` | `[{ prod: true }, "min"]` -`webpack --env.prod=foo --env.prod=bar` | `{prod: [ "foo", "bar" ]}` - -T> See the [environment variables](/guides/environment-variables) guide for more information on its usage. - -### Config Options - -Parameter | Explanation | Input type | Default -------------------------- | ------------------------------------------- | ---------- | ------------------ -`--config` | Path to the config file | string | webpack.config.js or webpackfile.js -`--config-register, -r` | Preload one or more modules before loading the webpack configuration | array | -`--config-name` | Name of the config to use | string | -`--env` | Environment passed to the config, when it is a function | | -`--mode` | Mode to use, either "development" or "production" | string | - -### Output Options - -This set of options allows you to manipulate certain [output](/configuration/output) parameters of your build. - -Parameter | Explanation | Input type | Default -------------------------- | ------------------------------------------- | ---------- | ------------------ -`--output-chunk-filename` | The output filename for additional chunks | string | filename with [id] instead of [name] or [id] prefixed -`--output-filename` | The output filename of the bundle | string | [name].js -`--output-jsonp-function` | The name of the JSONP function used for chunk loading | string | webpackJsonp -`--output-library` | Expose the exports of the entry point as library | string | -`--output-library-target` | The type for exposing the exports of the entry point as library | string | var -`--output-path` | The output path for compilation assets | string | Current directory -`--output-pathinfo` | Include a comment with the request for every dependency | boolean | false -`--output-public-path` | The public path for the assets | string | / -`--output-source-map-filename` | The output filename for the SourceMap | string | [name].map or [outputFilename].map -`--build-delimiter` | Display custom text after build output | string | Default string is null. You could provide a string such as `=== Build done ===` - - -#### Example Usage - -```bash -webpack index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' - -| Asset | Size | Chunks | Chunk Names | -|--------------------------------------|---------|-------------|---------------| -| index2740fdca26e9348bedbec.bundle.js | 2.6 kB | 0 [emitted] | index2 | -| index740fdca26e9348bedbec.bundle.js | 2.59 kB | 1 [emitted] | index | - [0] ./src/others.js 29 bytes {0} {1} [built] - [1] ./src/index.js 51 bytes {1} [built] - [2] ./src/index2.js 54 bytes {0} [built] -``` - -```bash -webpack.js index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' --devtool source-map --output-source-map-filename='[name]123.map' - -| Asset | Size | Chunks | Chunk Names | -|--------------------------------------|---------|-------------|---------------| -| index2740fdca26e9348bedbec.bundle.js | 2.76 kB | 0 [emitted] | index2 | -| index740fdca26e9348bedbec.bundle.js | 2.74 kB | 1 [emitted] | index | -| index2123.map | 2.95 kB | 0 [emitted] | index2 | -| index123.map | 2.95 kB | 1 [emitted] | index | - [0] ./src/others.js 29 bytes {0} {1} [built] - [1] ./src/index.js 51 bytes {1} [built] - [2] ./src/index2.js 54 bytes {0} [built] -``` - - -### Debug Options - -This set of options allows you to better debug the application containing assets compiled with webpack - -Parameter | Explanation | Input type | Default value ------------- | ------------------------------------------------ | ---------- | ------------- -`--debug` | Switch loaders to debug mode | boolean | false -`--devtool` | Define [source map type](/configuration/devtool/) for the bundled resources | string | - -`--progress` | Print compilation progress in percentage | boolean | false -`--display-error-details` | Display details about errors | boolean | false - -### Module Options - -These options allow you to bind [modules](/configuration/module/) as allowed by webpack - -Parameter | Explanation | Usage --------------------- | -------------------------------------- | ---------------- -`--module-bind` | Bind a file extension to a loader | `--module-bind js=babel-loader` -`--module-bind-post` | Bind a file extension to a post loader | -`--module-bind-pre` | Bind a file extension to a pre loader | - - -### Watch Options - -These options makes the build [watch](/configuration/watch/) for changes in files of the dependency graph and perform the build again. - -Parameter | Explanation -------------------------- | ---------------------- -`--watch`, `-w` | Watch the filesystem for changes -`--watch-aggregate-timeout` | Timeout for gathering changes while watching -`--watch-poll` | The polling interval for watching (also enable polling) -`--watch-stdin`, `--stdin` | Exit the process when stdin is closed - - -### Optimize Options - -These options allow you to manipulate optimisations for a production build using webpack - -Parameter | Explanation | Plugin Used ---------------------------- | -------------------------------------------------------|---------------------- -`--optimize-max-chunks` | Try to keep the chunk count below a limit | [LimitChunkCountPlugin](/plugins/limit-chunk-count-plugin) -`--optimize-min-chunk-size` | Try to keep the chunk size above a limit | [MinChunkSizePlugin](/plugins/min-chunk-size-plugin) -`--optimize-minimize` | Minimize javascript and switches loaders to minimizing | [TerserPlugin](/plugins/terser-webpack-plugin/) & [LoaderOptionsPlugin](/plugins/loader-options-plugin/) - - -### Resolve Options - -These allow you to configure the webpack [resolver](/configuration/resolve/) with aliases and extensions. - -Parameter | Explanation | Example ----------------------- | ------------------------------------------------------- | ------------- -`--resolve-alias` | Setup a module alias for resolving | --resolve-alias jquery-plugin=jquery.plugin -`--resolve-extensions` | Setup extensions that should be used to resolve modules | --resolve-extensions .es6 .js .ts -`--resolve-loader-alias` | Minimize javascript and switches loaders to minimizing | - - -### Stats Options - -These options allow webpack to display various [stats](/configuration/stats/) and style them differently in the console output. - -Parameter | Explanation | Type --------------------------------- | ------------------------------------------------------------------ | ------- -`--color`, `--colors` | Force colors on the console [default: enabled for TTY output only] | boolean -`--no-color`, `--no-colors` | Force no colors on the console | boolean -`--display` | Select [display preset](/configuration/stats) (verbose, detailed, normal, minimal, errors-only, none; since webpack 3.0.0) | string -`--display-cached` | Display also cached modules in the output | boolean -`--display-cached-assets` | Display also cached assets in the output | boolean -`--display-chunks` | Display chunks in the output | boolean -`--display-depth` | Display distance from entry point for each module | boolean -`--display-entrypoints` | Display entry points in the output | boolean -`--display-error-details` | Display details about errors | boolean -`--display-exclude` | Exclude modules in the output | boolean -`--display-max-modules` | Sets the maximum number of visible modules in output | number -`--display-modules` | Display even excluded modules in the output | boolean -`--display-optimization-bailout` | Scope hoisting fallback trigger (since webpack 3.0.0) | boolean -`--display-origins` | Display origins of chunks in the output | boolean -`--display-provided-exports` | Display information about exports provided from modules | boolean -`--display-reasons` | Display reasons about module inclusion in the output | boolean -`--display-used-exports` | Display information about used exports in modules (Tree Shaking) | boolean -`--hide-modules` | Hides info about modules | boolean -`--sort-assets-by` | Sorts the assets list by property in asset | string -`--sort-chunks-by` | Sorts the chunks list by property in chunk | string -`--sort-modules-by` | Sorts the modules list by property in module | string -`--verbose` | Show more details | boolean - - -### Advanced Options - -Parameter | Explanation | Usage ------------------ | ---------------------------------------- | ----- -`--bail` | Abort the compilation on first error | -`--cache` | Enable in memory caching [Enabled by default for watch] | `--cache=false` -`--define` | Define any free variable, see [shimming](/guides/shimming) | `--define process.env.NODE_ENV="'development'"` -`--hot` | Enables [Hot Module Replacement](/concepts/hot-module-replacement) | `--hot=true` -`--labeled-modules` | Enables labeled modules [Uses LabeledModulesPlugin] | -`--plugin` | Load this [plugin](/configuration/plugins/) | -`--prefetch` | Prefetch the particular file | `--prefetch=./files.js` -`--provide` | Provide these modules as globals, see [shimming](/guides/shimming) | `--provide jQuery=jquery` -`--records-input-path` | Path to the records file (reading) | -`--records-output-path` | Path to the records file (writing) | -`--records-path` | Path to the records file | -`--target` | The [targeted](/configuration/target/) execution environment | `--target='node'` - -### Shortcuts - -Shortcut | Replaces ----------|---------------------------- --d | `--debug --devtool cheap-module-eval-source-map --output-pathinfo` --p | `--optimize-minimize --define process.env.NODE_ENV="production"`, see [building for production](/guides/production) - -### Profiling - -The `--profile` option captures timing information for each step of the compilation and includes this in the output. - -```bash -webpack --profile - -⋮ -[0] ./src/index.js 90 bytes {0} [built] - factory:22ms building:16ms = 38ms -``` - -For each module, the following details are included in the output as applicable: - -- `factory`: time to collect module metadata (e.g. resolving the filename) -- `building`: time to build the module (e.g. loaders and parsing) -- `dependencies`: time to identify and connect the module’s dependencies - -Paired with `--progress`, `--profile` gives you an in depth idea of which step in the compilation is taking how long. This can help you optimise your build in a more informed manner. - -```bash -webpack --progress --profile - -30ms building modules -1ms sealing -1ms optimizing -0ms basic module optimization -1ms module optimization -1ms advanced module optimization -0ms basic chunk optimization -0ms chunk optimization -1ms advanced chunk optimization -0ms module and chunk tree optimization -1ms module reviving -0ms module order optimization -1ms module id optimization -1ms chunk reviving -0ms chunk order optimization -1ms chunk id optimization -10ms hashing -0ms module assets processing -13ms chunk assets processing -1ms additional chunk assets processing -0ms recording -0ms additional asset processing -26ms chunk asset optimization -1ms asset optimization -6ms emitting -⋮ -``` - - -# Compilation Hooks - -The `Compilation` module is used by the `Compiler` to create new compilations -(or builds). A `compilation` instance has access to all modules and their -dependencies (most of which are circular references). It is the literal -compilation of all the modules in the dependency graph of an application. -During the compilation phase, modules are loaded, sealed, optimized, chunked, -hashed and restored. - -The `Compilation` class also extends `Tapable` and provides the following -lifecycle hooks. They can be tapped the same way as compiler hooks: - -``` js -compilation.hooks.someHook.tap(/* ... */); -``` - -As with the `compiler`, `tapAsync` and `tapPromise` may also be available -depending on the type of hook. - - -### `buildModule` - -`SyncHook` - -Triggered before a module build has started. - -Parameters: `module` - - -### `rebuildModule` - -`SyncHook` - -Fired before rebuilding a module. - -Parameters: `module` - - -### `failedModule` - -`SyncHook` - -Run when a module build has failed. - -Parameters: `module` `error` - - -### `succeedModule` - -`SyncHook` - -Executed when a module has been built successfully. - -Parameters: `module` - - -### `finishModules` - -`SyncHook` - -All modules have been built. - -Parameters: `modules` - - -### `finishRebuildingModule` - -`SyncHook` - -A module has been rebuilt. - -Parameters: `module` - - -### `seal` - -`SyncHook` - -Fired when the compilation stops accepting new modules. - - -### `unseal` - -`SyncHook` - -Fired when a compilation begins accepting new modules. - - -### `optimizeDependenciesBasic` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeDependencies` - -`SyncBailHook` - -Fired at the beginning of dependency optimization. - -Parameters: `modules` - - -### `optimizeDependenciesAdvanced` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `afterOptimizeDependencies` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimize` - -`SyncHook` - -Triggered at the beginning of the optimization phase. - - -### `optimizeModulesBasic` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeModules` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeModulesAdvanced` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `afterOptimizeModules` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimizeChunksBasic` - -`SyncBailHook` - -... - -Parameters: `chunks` - - -### `optimizeChunks` - -`SyncBailHook` - -Optimize the chunks. - -Parameters: `chunks` - - -### `optimizeChunksAdvanced` - -`SyncBailHook` - -... - -Parameters: `chunks` - - -### `afterOptimizeChunks` - -`SyncHook` - -Fired after chunk optimization has completed. - -Parameters: `chunks` - - -### `optimizeTree` - -`AsyncSeriesHook` - -Optimize the dependency tree asynchronously. - -Parameters: `chunks` `modules` - - -### `afterOptimizeTree` - -`SyncHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModulesBasic` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModules` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModulesAdvanced` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `afterOptimizeChunkModules` - -`SyncHook` - -... - -Parameters: `chunks` `modules` - - -### `shouldRecord` - -`SyncBailHook` - -... - - -### `reviveModules` - -`SyncHook` - -Restore module information from records. - -Parameters: `modules` `records` - - -### `optimizeModuleOrder` - -`SyncHook` - -Sort the modules in from most to least important. - -Parameters: `modules` - - -### `advancedOptimizeModuleOrder` - -`SyncHook` - -... - -Parameters: `modules` - - -### `beforeModuleIds` - -`SyncHook` - -... - -Parameters: `modules` - - -### `moduleIds` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimizeModuleIds` - -`SyncHook` - -... - -Parameters: `chunks` - - -### `afterOptimizeModuleIds` - -`SyncHook` - -... - -Parameters: `chunks` - - -### `reviveChunks` - -`SyncHook` - -Restore chunk information from records. - -Parameters: `modules` `records` - - -### `optimizeChunkOrder` - -`SyncHook` - -Sort the chunks in from most to least important. - -Parameters: `chunks` - - -### `beforeOptimizeChunkIds` - -`SyncHook` - -Fired before chunk `id` optimization. - -Parameters: `chunks` - - -### `optimizeChunkIds` - -`SyncHook` - -Optimize the `id` of each chunk. - -Parameters: `chunks` - - -### `afterOptimizeChunkIds` - -`SyncHook` - -Triggered after chunk `id` optimization has finished. - -Parameters: `chunks` - - -### `recordModules` - -`SyncHook` - -Store module info to the records. - -Parameters: `modules` `records` - - -### `recordChunks` - -`SyncHook` - -Store chunk info to the records. - -Parameters: `chunks` `records` - - -### `beforeHash` - -`SyncHook` - -Before the compilation is hashed. - - -### `afterHash` - -`SyncHook` - -After the compilation is hashed. - - -### `recordHash` - -`SyncHook` - -... - -Parameters: `records` - - -### `record` - -`SyncHook` - -Store information about the `compilation` to the `records`. - -Parameters: `compilation` `records` - - -### `beforeModuleAssets` - -`SyncHook` - -... - - -### `shouldGenerateChunkAssets` - -`SyncBailHook` - -... - - -### `beforeChunkAssets` - -`SyncHook` - -Before creating the chunk assets. - - -### `additionalChunkAssets` - -`SyncHook` - -Create additional assets for the chunks. - -Parameters: `chunks` - - -### `records` - -`SyncHook` - -... - -Parameters: `compilation` `records` - - -### `additionalAssets` - -`AsyncSeriesHook` - -Create additional assets for the compilation. This hook can be used to download -an image, for example: - -``` js -compilation.hooks.additionalAssets.tapAsync('MyPlugin', callback => { - download('https://img.shields.io/npm/v/webpack.svg', function(resp) { - if(resp.status === 200) { - compilation.assets['webpack-version.svg'] = toAsset(resp); - callback(); - } else { - callback(new Error('[webpack-example-plugin] Unable to download the image')); - } - }); -}); -``` - - -### `optimizeChunkAssets` - -`AsyncSeriesHook` - -Optimize any chunk assets. The assets are stored in `compilation.assets`. A -`Chunk` has a property `files` which points to all files created by a chunk. -Any additional chunk assets are stored in `compilation.additionalChunkAssets`. - -Parameters: `chunks` - -Here's an example that simply adds a banner to each chunk. - -``` js -compilation.hooks - .optimizeChunkAssets - .tapAsync('MyPlugin', (chunks, callback) => { - chunks.forEach(chunk => { - chunk.files.forEach(file => { - compilation.assets[file] = new ConcatSource( - '\/**Sweet Banner**\/', - '\n', - compilation.assets[file] - ); - }); - }); - - callback(); - }); -``` - - -### `afterOptimizeChunkAssets` - -`SyncHook` - -The chunk assets have been optimized. - -Parameters: `chunks` - -Here's an example plugin from [@boopathi](https://github.com/boopathi) that outputs exactly what went into each chunk. - -``` js -compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', chunks => { - chunks.forEach(chunk => { - console.log({ - id: chunk.id, - name: chunk.name, - includes: chunk.modules.map(module => module.request) - }); - }); -}); -``` - - -### `optimizeAssets` - -`AsyncSeriesHook` - -Optimize all assets stored in `compilation.assets`. - -Parameters: `assets` - - -### `afterOptimizeAssets` - -`SyncHook` - -The assets has been optimized. - -Parameters: `assets` - - -### `needAdditionalSeal` - -`SyncBailHook` - -... - - -### `afterSeal` - -`AsyncSeriesHook` - -... - - -### `chunkHash` - -`SyncHook` - -... - -Parameters: `chunk` `chunkHash` - - -### `moduleAsset` - -`SyncHook` - -An asset from a module was added to the compilation. - -Parameters: `module` `filename` - - -### `chunkAsset` - -`SyncHook` - -An asset from a chunk was added to the compilation. - -Parameters: `chunk` `filename` - - -### `assetPath` - -`SyncWaterfallHook` - -... - -Parameters: `filename` `data` - - -### `needAdditionalPass` - -`SyncBailHook` - -... - - -### `childCompiler` - -`SyncHook` - -... - -Parameters: `childCompiler` `compilerName` `compilerIndex` - - -### `normalModuleLoader` - -`SyncHook` - -The normal module loader is the function that actually loads all the modules -in the module graph (one-by-one). - -Parameters: `loaderContext` `module` - -### `dependencyReference` - -`SyncWaterfallHook` - -`Compilation.hooks.dependencyReference(depRef, dependency, module)` allows to change the references reported by dependencies. - -Parameters: `depRef` `dependency` `module` - - -# Module Methods - -This section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including [ES6](https://en.wikipedia.org/wiki/ECMAScript#6th_Edition_-_ECMAScript_2015), [CommonJS](https://en.wikipedia.org/wiki/CommonJS), and [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition). - -W> While webpack supports multiple module syntaxes, we recommend following a single syntax for consistency and to avoid odd behaviors/bugs. Here's [one example](https://github.com/webpack/webpack.js.org/issues/552) of mixing ES6 and CommonJS, however there are surely others. - - -## ES6 (Recommended) - -Version 2 of webpack supports ES6 module syntax natively, meaning you can use `import` and `export` without a tool like babel to handle this for you. Keep in mind that you will still probably need babel for other ES6+ features. The following methods are supported by webpack: - - -### `import` - -Statically `import` the `export`s of another module. - -``` javascript -import MyModule from './my-module.js'; -import { NamedExport } from './other-module.js'; -``` - -W> The keyword here is __statically__. Normal `import` statement cannot be used dynamically within other logic or contain variables. See the [spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) for more information and `import()` below for dynamic usage. - - -### `export` - -Export anything as a `default` or named export. - -``` javascript -// Named exports -export var Count = 5; -export function Multiply(a, b) { - return a * b; -} - -// Default export -export default { - // Some data... -}; -``` - - -### `import()` - -`import('path/to/module') -> Promise` - -Dynamically load modules. Calls to `import()` are treated as split points, meaning the requested module and it's children are split out into a separate chunk. - -T> The [ES2015 Loader spec](https://whatwg.github.io/loader/) defines `import()` as method to load ES2015 modules dynamically on runtime. - -``` javascript -if ( module.hot ) { - import('lodash').then(_ => { - // Do something with lodash (a.k.a '_')... - }); -} -``` - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -The spec for `import` doesn't allow control over the chunk's name or other properties as "chunks" are only a concept within webpack. Luckily webpack allows some special parameters via comments so as to not break the spec: - -``` js -// Single target -import( - /* webpackChunkName: "my-chunk-name" */ - /* webpackMode: "lazy" */ - 'module' -); - -// Multiple possible targets -import( - /* webpackInclude: /\.json$/ */ - /* webpackExclude: /\.noimport\.json$/ */ - /* webpackChunkName: "my-chunk-name" */ - /* webpackMode: "lazy" */ - `./locale/${language}` -); -``` - -```js -import(/* webpackIgnore: true */ 'ignored-module.js'); -``` - -`webpackIgnore`: Disables dynamic import parsing when set to `true`. - -W> Note that setting `webpackIgnore` to `true` opts out of code splitting. - -`webpackChunkName`: A name for the new chunk. Since webpack 2.6.0, the placeholders `[index]` and `[request]` are supported within the given string to an incremented number or the actual resolved filename respectively. - -`webpackMode`: Since webpack 2.6.0, different modes for resolving dynamic imports can be specified. The following options are supported: - -- `"lazy"` (default): Generates a lazy-loadable chunk for each `import()`ed module. -- `"lazy-once"`: Generates a single lazy-loadable chunk that can satisfy all calls to `import()`. The chunk will be fetched on the first call to `import()`, and subsequent calls to `import()` will use the same network response. Note that this only makes sense in the case of a partially dynamic statement, e.g. ``import(`./locales/${language}.json`)``, where there are multiple module paths that could potentially be requested. -- `"eager"`: Generates no extra chunk. All modules are included in the current chunk and no additional network requests are made. A `Promise` is still returned but is already resolved. In contrast to a static import, the module isn't executed until the call to `import()` is made. -- `"weak"`: Tries to load the module if the module function has already been loaded in some other way (i. e. another chunk imported it or a script containing the module was loaded). A `Promise` is still returned but, only successfully resolves if the chunks are already on the client. If the module is not available, the `Promise` is rejected. A network request will never be performed. This is useful for universal rendering when required chunks are always manually served in initial requests (embedded within the page), but not in cases where app navigation will trigger an import not initially served. - -T> Note that all options can be combined like so `/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */`. This is wrapped in a JavaScript object and executed using [node VM](https://nodejs.org/dist/latest-v8.x/docs/api/vm.html). You do not need to add curly brackets. - -`webpackInclude`: A regular expression that will be matched against during import resolution. Only modules that match __will be bundled__. - -`webpackExclude`: A regular expression that will be matched against during import resolution. Any module that matches __will not be bundled__. - -T> Note that `webpackInclude` and `webpackExclude` options do not interfere with the prefix. eg: `./locale`. - -W> Fully dynamic statements, such as `import(foo)`, __will fail__ because webpack requires at least some file location information. This is because `foo` could potentially be any path to any file in your system or project. The `import()` must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files. - -W> Every module that could potentially be requested on an `import()` call is included. For example, ``import(`./locale/${language}.json`)`` will cause every `.json` file in the `./locale` directory to be bundled into the new chunk. At run time, when the variable `language` has been computed, any file like `english.json` or `german.json` will be available for consumption. Using the `webpackInclude` and `webpackExclude` options allows us to add regex patterns that reduce the files that webpack will bundle for this import. - -W> The use of `System.import` in webpack [did not fit the proposed spec](https://github.com/webpack/webpack/issues/2163), so it was deprecated in webpack [2.1.0-beta.28](https://github.com/webpack/webpack/releases/tag/v2.1.0-beta.28) in favor of `import()`. - - -## CommonJS - -The goal of CommonJS is to specify an ecosystem for JavaScript outside the browser. The following CommonJS methods are supported by webpack: - - -### `require` - -``` javascript -require(dependency: String); -``` - -Synchronously retrieve the exports from another module. The compiler will ensure that the dependency is available in the output bundle. - -``` javascript -var $ = require('jquery'); -var myModule = require('my-module'); -``` - -W> Using it asynchronously may not have the expected effect. - - -### `require.resolve` - -``` javascript -require.resolve(dependency: String); -``` - -Synchronously retrieve a module's ID. The compiler will ensure that the dependency is available in the output bundle. See [`module.id`](/api/module-variables#module-id-commonjs-) for more information. - -W> Module ID is a number in webpack (in contrast to NodeJS where it is a string -- the filename). - - -### `require.cache` - -Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. - -W> This is only needed in rare cases for compatibility! - -``` javascript -var d1 = require('dependency'); -require('dependency') === d1; -delete require.cache[require.resolve('dependency')]; -require('dependency') !== d1; -``` - -``` javascript -// in file.js -require.cache[module.id] === module; -require('./file.js') === module.exports; -delete require.cache[module.id]; -require.cache[module.id] === undefined; -require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow -require.cache[module.id] !== module; -``` - - -### `require.ensure` - -W> `require.ensure()` is specific to webpack and superseded by `import()`. - -<!-- eslint-skip --> - -```js -require.ensure( - dependencies: String[], - callback: function(require), - errorCallback: function(error), - chunkName: String -) -``` - -Split out the given `dependencies` to a separate bundle that that will be loaded asynchronously. When using CommonJS module syntax, this is the only way to dynamically load dependencies. Meaning, this code can be run within execution, only loading the `dependencies` if certain conditions are met. - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `require.ensure` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -``` javascript -var a = require('normal-dep'); - -if ( module.hot ) { - require.ensure(['b'], function(require) { - var c = require('c'); - - // Do something special... - }); -} -``` - -The following parameters are supported in the order specified above: - -- `dependencies`: An array of strings declaring all modules required for the code in the `callback` to execute. -- `callback`: A function that webpack will execute once the dependencies are loaded. An implementation of the `require` function is sent as a parameter to this function. The function body can use this to further `require()` modules it needs for execution. -- `errorCallback`: A function that is executed when webpack fails to load the dependencies. -- `chunkName`: A name given to the chunk created by this particular `require.ensure()`. By passing the same `chunkName` to various `require.ensure()` calls, we can combine their code into a single chunk, resulting in only one bundle that the browser must load. - -W> Although the implementation of `require` is passed as an argument to the `callback` function, using an arbitrary name e.g. `require.ensure([], function(request) { request('someModule'); })` isn't handled by webpack's static parser. Use `require` instead, e.g. `require.ensure([], function(require) { require('someModule'); })`. - - - -## AMD - -Asynchronous Module Definition (AMD) is a JavaScript specification that defines an interface for writing and loading modules. The following AMD methods are supported by webpack: - - -### `define` (with factory) - -<!-- eslint-skip --> - -```js -define([name: String], [dependencies: String[]], factoryMethod: function(...)) -``` - -If `dependencies` are provided, `factoryMethod` will be called with the exports of each dependency (in the same order). If `dependencies` are not provided, `factoryMethod` is called with `require`, `exports` and `module` (for compatibility!). If this function returns a value, this value is exported by the module. The compiler ensures that each dependency is available. - -W> Note that webpack ignores the `name` argument. - -``` javascript -define(['jquery', 'my-module'], function($, myModule) { - // Do something with $ and myModule... - - // Export a function - return function doSomething() { - // ... - }; -}); -``` - -W> This CANNOT be used in an asynchronous function. - - -### `define` (with value) - -<!-- eslint-skip --> - -```js -define(value: !Function) -``` - -This will simply export the provided `value`. The `value` here can be anything except a function. - -``` javascript -define({ - answer: 42 -}); -``` - -W> This CANNOT be used in an async function. - - -### `require` (amd-version) - -<!-- eslint-skip --> - -```js -require(dependencies: String[], [callback: function(...)]) -``` - -Similar to `require.ensure`, this will split the given `dependencies` into a separate bundle that will be loaded asynchronously. The `callback` will be called with the exports of each dependency in the `dependencies` array. - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use AMD with older browsers (e.g. Internet Explorer 11), remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -``` javascript -require(['b'], function(b) { - var c = require('c'); -}); -``` - -W> There is no option to provide a chunk name. - - - -## Labeled Modules - -The internal `LabeledModulesPlugin` enables you to use the following methods for exporting and requiring within your modules: - - -### `export` label - -Export the given `value`. The label can occur before a function declaration or a variable declaration. The function name or variable name is the identifier under which the value is exported. - -<!-- eslint-skip --> - -```js -export: var answer = 42; -export: function method(value) { - // Do something... -}; -``` - -W> Using it in an async function may not have the expected effect. - - -### `require` label - -Make all exports from the dependency available in the current scope. The `require` label can occur before a string. The dependency must export values with the `export` label. CommonJS or AMD modules cannot be consumed. - -__some-dependency.js__ - -<!-- eslint-skip --> - -```js -export: var answer = 42; -export: function method(value) { - // Do something... -}; -``` - -<!-- eslint-skip --> - -```js -require: 'some-dependency'; -console.log(answer); -method(...); -``` - - - -## Webpack - -Aside from the module syntaxes described above, webpack also allows a few custom, webpack-specific methods: - - -### `require.context` - -<!-- eslint-skip --> - -```js -require.context( - directory: String, - includeSubdirs: Boolean /* optional, default true */, - filter: RegExp /* optional, default /^\.\/.*$/, any file */, - mode: String /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */ -) -``` - -Specify a whole group of dependencies using a path to the `directory`, an option to `includeSubdirs`, a `filter` for more fine grained control of the modules included, and a `mode` to define the way how loading will work. Underlying modules can then be easily resolved later on: - -```javascript -var context = require.context('components', true, /\.html$/); -var componentA = context.resolve('componentA'); -``` - -If `mode` is specified as "lazy", the underlying modules will be loaded asynchronously: - -```javascript -var context = require.context('locales', true, /\.json$/, 'lazy'); -context('localeA').then(locale => { - // do something with locale -}); -``` - -The full list of available modes and its behavior is described in [`import()`](#import-) documentation. - -### `require.include` - -<!-- eslint-skip --> - -```js -require.include(dependency: String) -``` - -Include a `dependency` without executing it. This can be used for optimizing the position of a module in the output chunks. - -``` javascript -require.include('a'); -require.ensure(['a', 'b'], function(require) { /* ... */ }); -require.ensure(['a', 'c'], function(require) { /* ... */ }); -``` - -This will result in following output: - -- entry chunk: `file.js` and `a` -- anonymous chunk: `b` -- anonymous chunk: `c` - -Without `require.include('a')` it would be duplicated in both anonymous chunks. - - -### `require.resolveWeak` - -Similar to `require.resolve`, but this won't pull the `module` into the bundle. It's what is considered a "weak" dependency. - -``` javascript -if(__webpack_modules__[require.resolveWeak('module')]) { - // Do something when module is available... -} -if(require.cache[require.resolveWeak('module')]) { - // Do something when module was loaded before... -} - -// You can perform dynamic resolves ("context") -// just as with other require/import methods. -const page = 'Foo'; -__webpack_modules__[require.resolveWeak(`./page/${page}`)]; -``` - -T> `require.resolveWeak` is the foundation of _universal rendering_ (SSR + Code Splitting), as used in packages such as [react-universal-component](https://github.com/faceyspacey/react-universal-component). It allows code to render synchronously on both the server and initial page-loads on the client. It requires that chunks are manually served or somehow available. It's able to require modules without indicating they should be bundled into a chunk. It's used in conjunction with `import()` which takes over when user navigation triggers additional imports. - - -# Node.js API - -webpack provides a Node.js API which can be used directly in Node.js runtime. - -The Node.js API is useful in scenarios in which you need to customize the build or development process since all the reporting and error handling must be done manually and webpack only does the compiling part. For this reason the [`stats`](/configuration/stats) configuration options will not have any effect in the `webpack()` call. - - -## Installation - -To start using webpack Node.js API, first install webpack if you haven’t yet: - -``` bash -npm install --save-dev webpack -``` - -Then require the webpack module in your Node.js script: - -``` js -const webpack = require('webpack'); -``` - -Or if you prefer ES2015: - -``` js -import webpack from 'webpack'; -``` - - -## `webpack()` - -The imported `webpack` function is fed a webpack [Configuration Object](/configuration/) and runs the webpack compiler if a callback function is provided: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, [stats](#stats-object)) => { - if (err || stats.hasErrors()) { - // [Handle errors here](#error-handling) - } - // Done processing -}); -``` - -T> The `err` object __will not__ include compilation errors and those must be handled separately using `stats.hasErrors()` which will be covered in detail in [Error Handling](#error-handling) section of this guide. The `err` object will only contain webpack-related issues, such as misconfiguration, etc. - -T> You can provide the `webpack` function with an array of configurations. See -the [MultiCompiler](#multicompiler) section below for more information. - - -## Compiler Instance - -If you don’t pass the `webpack` runner function a callback, it will return a -webpack `Compiler` instance. This instance can be used to manually trigger the -webpack runner or have it build and watch for changes, much like the -[CLI](/api/cli/). The `Compiler` instance provides the following methods: - -- `.run(callback)` -- `.watch(watchOptions, handler)` - -Typically, only one master `Compiler` instance is created, although child -compilers can be created in order to delegate specific tasks. The `Compiler` is -ultimately just a function which performs bare minimum functionality to keep a -lifecycle running. It delegates all the loading, bundling, and writing work to -registered plugins. - -The `hooks` property on a `Compiler` instance is used to register a plugin to -any hook event in the `Compiler`'s lifecycle. The -[`WebpackOptionsDefaulter`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js) -and [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js) -utilities are used by webpack to configure its `Compiler` instance with all the -built-in plugins. - -The `run` method is then used to kickstart all compilation work. Upon -completion, the given `callback` function is executed. The final logging of -stats and errors should be done in this `callback` function. - -W> The API only supports a single concurrent compilation at a time. When using -`run`, wait for it to finish before calling `run` or `watch` again. When using -`watch`, call `close` and wait for it to finish before calling `run` or `watch` -again. Concurrent compilations will corrupt the output files. - - -## Run - -Calling the `run` method on the `Compiler` instance is much like the quick run -method mentioned above: - -``` js-with-links -const webpack = require("webpack"); - -const compiler = webpack({ - // [Configuration Object](/configuration/) -}); - -compiler.run((err, [stats](#stats-object)) => { - // ... -}); -``` - - -## Watching - -Calling the `watch` method, triggers the webpack runner, but then watches for -changes (much like CLI: `webpack --watch`), as soon as webpack detects a -change, runs again. Returns an instance of `Watching`. - -``` js -watch(watchOptions, callback); -``` - -``` js-with-links -const webpack = require("webpack"); - -const compiler = webpack({ - // [Configuration Object](/configuration/) -}); - -const watching = compiler.watch({ - // Example [watchOptions](/configuration/watch/#watchoptions) - aggregateTimeout: 300, - poll: undefined -}, (err, [stats](#stats-object)) => { - // Print watch/build result here... - console.log(stats); -}); -``` - -`Watching` options are covered in detail -[here](/configuration/watch/#watchoptions). - -W> Filesystem inaccuracies may trigger multiple builds for a single change. So, -in the example above, the `console.log` statement may fire multiple times for a -single modification. Users should expect this behavior and may check -`stats.hash` to see if the file hash has actually changed. - - -### Close `Watching` - -The `watch` method returns a `Watching` instance that exposes -`.close(callback)` method. Calling this method will end watching: - -``` js -watching.close(() => { - console.log('Watching Ended.'); -}); -``` - -W> It’s not allowed to watch or run again before the existing watcher has been -closed or invalidated. - - -### Invalidate `Watching` - -Using `watching.invalidate`, you can manually invalidate the current compiling -round, without stopping the watch process: - -``` js -watching.invalidate(); -``` - - -## Stats Object - -The `stats` object that is passed as a second argument of the -[`webpack()`](#webpack-) callback, is a good source of information about the -code compilation process. It includes: - -- Errors and Warnings (if any) -- Timings -- Module and Chunk information - -The [webpack CLI](/api/cli) uses this information to display nicely formatted -output in your console. - -T> When using the [`MultiCompiler`](/api/plugins/compiler#multicompiler), a -`MultiStats` instance is returned that fulfills the same interface as `stats`, -i.e. the methods described below. - -This `stats` object exposes the following methods: - - -### `stats.hasErrors()` - -Can be used to check if there were errors while compiling. Returns `true` or -`false`. - - -### `stats.hasWarnings()` - -Can be used to check if there were warnings while compiling. Returns `true` or -`false`. - - -### `stats.toJson(options)` - -Returns compilation information as a JSON object. `options` can be either a -string (a preset) or an object for more granular control: - -``` js-with-links -stats.toJson("minimal"); // [more options: "verbose", etc](/configuration/stats). -``` - -``` js -stats.toJson({ - assets: false, - hash: true -}); -``` - -All available options and presets are described in the stats [documentation](/configuration/stats). - -> Here’s an [example] -(https://github.com/webpack/analyse/blob/master/app/pages/upload/example.json) -of this function’s output. - - -### `stats.toString(options)` - -Returns a formatted string of the compilation information (similar to -[CLI](/api/cli) output). - -Options are the same as [`stats.toJson(options)`](/api/node#stats-tojson-options-) with one addition: - -``` js -stats.toString({ - // Add console colors - colors: true -}); -``` - -Here’s an example of `stats.toString()` usage: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, stats) => { - if (err) { - console.error(err); - return; - } - - console.log(stats.toString({ - chunks: false, // Makes the build much quieter - colors: true // Shows colors in the console - })); -}); -``` - - -## MultiCompiler - -The `MultiCompiler` module allows webpack to run multiple configurations in -separate compilers. If the `options` parameter in the webpack's NodeJS api is -an array of options, webpack applies separate compilers and calls the -`callback` method at the end of each compiler execution. - -``` js-with-links -var webpack = require('webpack'); - -webpack([ - { entry: './index1.js', output: { filename: 'bundle1.js' } }, - { entry: './index2.js', output: { filename: 'bundle2.js' } } -], (err, [stats](#stats-object)) => { - process.stdout.write(stats.toString() + "\n"); -}) -``` - -W> Multiple configurations will __not be run in parallel__. Each -configuration is only processed after the previous one has finished -processing. To process them in parallel, you can use a third-party solution -like [parallel-webpack](https://www.npmjs.com/package/parallel-webpack). - - -## Error Handling - -For a good error handling, you need to account for these three types of errors: - -- Fatal webpack errors (wrong configuration, etc) -- Compilation errors (missing modules, syntax errors, etc) -- Compilation warnings - -Here’s an example that does all that: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, stats) => { - if (err) { - console.error(err.stack || err); - if (err.details) { - console.error(err.details); - } - return; - } - - const info = stats.toJson(); - - if (stats.hasErrors()) { - console.error(info.errors); - } - - if (stats.hasWarnings()) { - console.warn(info.warnings); - } - - // Log result... -}); -``` - - -## Custom File Systems - -By default, webpack reads files and writes files to disk using a normal file -system. However, it is possible to change the input or output behavior using a -different kind of file system (memory, webDAV, etc). To accomplish this, one -can change the `inputFileSystem` or `outputFileSystem`. For example, you can -replace the default `outputFileSystem` with -[`memory-fs`](https://github.com/webpack/memory-fs) to write files to memory -instead of to disk: - -``` js -const MemoryFS = require('memory-fs'); -const webpack = require('webpack'); - -const fs = new MemoryFS(); -const compiler = webpack({ /* options*/ }); - -compiler.outputFileSystem = fs; -compiler.run((err, stats) => { - // Read the output later: - const content = fs.readFileSync('...'); -}); -``` - -Note that this is what -[webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware), -used by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) -and many other packages, uses to mysteriously hide your files but continue -serving them up to the browser! - -T> The output file system you provide needs to be compatible with Node’s own -[`fs`](https://nodejs.org/api/fs.html) interface, which requires the `mkdirp` -and `join` helper methods. - - -# Resolvers - -Resolvers are created using the `enhanced-resolve` package. The `Resolver` -class extends the `tapable` class and uses `tapable` to provide a few hooks. -The `enhanced-resolve` package can be used directly to create new resolvers, -however any [`compiler` instance](/api/node/#compiler-instance) has a few resolver instances that can be -tapped into. - -Before reading on, make sure you at least skim through the -[`enhanced-resolve`](https://github.com/webpack/enhanced-resolve) and [`tapable`](/api/plugins/#tapable) documentation. - - -## Types - -There are three types of built-in resolvers available on the `compiler` class: - -- Normal: Resolves a module via an absolute or relative path. -- Context: Resolves a module within a given context. -- Loader: Resolves a webpack [loader](/loaders). - -Depending on need, any one of these built-in resolver used by the `compiler` -can be customized via plugins as such: - -``` js -compiler.resolverFactory.plugin('resolver [type]', resolver => { - resolver.hooks.resolve.tapAsync('MyPlugin', params => { - // ... - }); -}); -``` - -Where `[type]` is one of the three resolvers mention above, specified as: - -- `normal` -- `context` -- `loader` - - -See the `enhanced-resolve` [documentation](https://github.com/webpack/enhanced-resolve) for a full list of hooks and -descriptions. - - -## Configuration Options - -The resolvers mentioned above can also be customized via a configuration file -with the [`resolve`](/configuration/resolve/) or [`resolveLoader`](/configuration/resolve/#resolveloader) options. These options allow -users to change the resolving behavior through a variety of options including -through resolve `plugins`. - -The resolver plugins, e.g. [`DirectoryNamedPlugin`](https://github.com/shaketbaby/directory-named-webpack-plugin), can be included -directly in `resolve.plugins` rather than using standard plugins. Note that the -`resolve` configuration affects the `normal` and `context` resolvers while -`resolveLoader` is used to modify the `loader` resolver. - - -# Stats Data - -When compiling source code with webpack, users can generate a JSON file containing statistics about modules. These statistics can be used to analyze an application's dependency graph as well as to optimize compilation speed. The file is typically generated with the following CLI command: - -``` bash -webpack --profile --json > compilation-stats.json -``` - -The `--json > compilation-stats.json` flag indicates to webpack that it should emit the `compilation-stats.json` containing the dependency graph and various other build information. Typically, the `--profile` flag is also added so that a `profile` section is added to each [`modules` object](#module-objects) containing module-specific compilation stats. - - -## Structure - -The top-level structure of the output JSON file is fairly straightforward but there are a few nested data structures as well. Each nested structure has a dedicated section below to make this document more consumable. Note that you can click links within the top-level structure below to jump to relevant sections and documentation: - -```js-with-links -{ - "version": "1.4.13", // Version of webpack used for the compilation - "hash": "11593e3b3ac85436984a", // Compilation specific hash - "time": 2469, // Compilation time in milliseconds - "filteredModules": 0, // A count of excluded modules when [`exclude`](/configuration/stats/#stats) is passed to the [`toJson`](/api/node/#stats-tojson-options-) method - "outputPath": "/", // path to webpack output directory - "assetsByChunkName": { - // Chunk name to emitted asset(s) mapping - "main": "web.js?h=11593e3b3ac85436984a", - "named-chunk": "named-chunk.web.js", - "other-chunk": [ - "other-chunk.js", - "other-chunk.css" - ] - }, - "assets": [ - // A list of [asset objects](#asset-objects) - ], - "chunks": [ - // A list of [chunk objects](#chunk-objects) - ], - "modules": [ - // A list of [module objects](#module-objects) - ], - "errors": [ - // A list of [error strings](#errors-and-warnings) - ], - "warnings": [ - // A list of [warning strings](#errors-and-warnings) - ] -} -``` - - -### Asset Objects - -Each `assets` object represents an `output` file emitted from the compilation. They all follow a similar structure: - -<!-- eslint-skip --> - -```js -{ - "chunkNames": [], // The chunks this asset contains - "chunks": [ 10, 6 ], // The chunk IDs this asset contains - "emitted": true, // Indicates whether or not the asset made it to the `output` directory - "name": "10.web.js", // The `output` filename - "size": 1058 // The size of the file in bytes -} -``` - - -### Chunk Objects - -Each `chunks` object represents a group of modules known as a [chunk](/glossary#c). Each object follows the following structure: - -```js-with-links -{ - "entry": true, // Indicates whether or not the chunk contains the webpack runtime - "files": [ - // An array of filename strings that contain this chunk - ], - "filteredModules": 0, // See the description in the [top-level structure](#structure) above - "id": 0, // The ID of this chunk - "initial": true, // Indicates whether this chunk is loaded on initial page load or [on demand](/guides/lazy-loading) - "modules": [ - // A list of [module objects](#module-objects) - "web.js?h=11593e3b3ac85436984a" - ], - "names": [ - // An list of chunk names contained within this chunk - ], - "origins": [ - // See the description below... - ], - "parents": [], // Parent chunk IDs - "rendered": true, // Indicates whether or not the chunk went through Code Generation - "size": 188057 // Chunk size in bytes -} -``` - -The `chunks` object will also contain a list of `origins` describing how the given chunk originated. Each `origins` object follows the following schema: - -```js-with-links -{ - "loc": "", // Lines of code that generated this chunk - "module": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleId": 0, // The ID of the module - "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleName": "./lib/index.web.js", // Relative path to the module - "name": "main", // The name of the chunk - "reasons": [ - // A list of the same `reasons` found in [module objects](#module-objects) - ] -} -``` - - -### Module Objects - -What good would these statistics be without some description of the compiled application's actual modules? Each module in the dependency graph is represented by the following structure: - -```js-with-links -{ - "assets": [ - // A list of [asset objects](#asset-objects) - ], - "built": true, // Indicates that the module went through [Loaders](/concepts/loaders), Parsing, and Code Generation - "cacheable": true, // Whether or not this module is cacheable - "chunks": [ - // IDs of chunks that contain this module - ], - "errors": 0, // Number of errors when resolving or processing the module - "failed": false, // Whether or not compilation failed on this module - "id": 0, // The ID of the module (analagous to [`module.id`](/api/module-variables#module-id-commonjs-)) - "identifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // A unique ID used internally - "name": "./lib/index.web.js", // Path to the actual file - "optional": false, // All requests to this module are with `try... catch` blocks (irrelevant with ESM) - "prefetched": false, // Indicates whether or not the module was [prefetched](/plugins/prefetch-plugin) - "profile": { - // Module specific compilation stats corresponding to the [`--profile` flag](/api/cli#profiling) (in milliseconds) - "building": 73, // Loading and parsing - "dependencies": 242, // Building dependencies - "factory": 11 // Resolving dependencies - }, - "reasons": [ - // See the description below... - ], - "size": 3593, // Estimated size of the module in bytes - "source": "// Should not break it...\r\nif(typeof...", // The stringified raw source - "warnings": 0 // Number of warnings when resolving or processing the module -} -``` - -Every module also contains a list of `reasons` objects describing why that module was included in the dependency graph. Each "reason" is similar to the `origins` seen above in the [chunk objects](#chunk-objects) section: - -```js-with-links -{ - "loc": "33:24-93", // Lines of code that caused the module to be included - "module": "./lib/index.web.js", // Relative path to the module based on [context](/configuration/entry-context/#context) - "moduleId": 0, // The ID of the module - "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleName": "./lib/index.web.js", // A more readable name for the module (used for "pretty-printing") - "type": "require.context", // The [type of request](/api/module-methods) used - "userRequest": "../../cases" // Raw string used for the `import` or `require` request -} -``` - - -### Errors and Warnings - -The `errors` and `warnings` properties each contain a list of strings. Each string contains a message and stack trace: - -``` bash -../cases/parsing/browserify/index.js -Critical dependencies: -2:114-121 This seem to be a pre-built javascript file. Even while this is possible, it's not recommended. Try to require to original source to get better results. - @ ../cases/parsing/browserify/index.js 2:114-121 -``` - -W> Note that the stack traces are removed when `errorDetails: false` is passed to the `toJson` method. The `errorDetails` option is set to `true` by default. - - -# Loader API - -A loader is just a JavaScript module that exports a function. The [loader runner](https://github.com/webpack/loader-runner) calls this function and passes the result of the previous loader or the resource file into it. The `this` context of the function is filled-in by webpack and the [loader runner](https://github.com/webpack/loader-runner) with some useful methods that allow the loader (among other things) to change its invocation style to async, or get query parameters. - -The first loader is passed one argument: the content of the resource file. The compiler expects a result from the last loader. The result should be a `String` or a `Buffer` (which is converted to a string), representing the JavaScript source code of the module. An optional SourceMap result (as JSON object) may also be passed. - -A single result can be returned in __sync mode__. For multiple results the `this.callback()` must be called. In __async mode__ `this.async()` must be called to indicate that the [loader runner](https://github.com/webpack/loader-runner) should wait for an asynchronous result. It returns `this.callback()`. Then the loader must return `undefined` and call that callback. - - -## Examples - -The following sections provide some basic examples of the different types of loaders. Note that the `map` and `meta` parameters are optional, see [`this.callback`](/api/loaders#this-callback) below. - -### Synchronous Loaders - -Either `return` or `this.callback` can be used to return the transformed `content` synchronously: - -__sync-loader.js__ - -``` js -module.exports = function(content, map, meta) { - return someSyncOperation(content); -}; -``` - -The `this.callback` method is more flexible as it allows multiple arguments to be passed as opposed to just the `content`. - -__sync-loader-with-multiple-results.js__ - -``` js -module.exports = function(content, map, meta) { - this.callback(null, someSyncOperation(content), map, meta); - return; // always return undefined when calling callback() -}; -``` - -### Asynchronous Loaders - -For asynchronous loaders, [`this.async`](/api/loaders#this-async) is used to retrieve the `callback` function: - -__async-loader.js__ - -``` js -module.exports = function(content, map, meta) { - var callback = this.async(); - someAsyncOperation(content, function(err, result) { - if (err) return callback(err); - callback(null, result, map, meta); - }); -}; -``` - -__async-loader-with-multiple-results.js__ - -``` js -module.exports = function(content, map, meta) { - var callback = this.async(); - someAsyncOperation(content, function(err, result, sourceMaps, meta) { - if (err) return callback(err); - callback(null, result, sourceMaps, meta); - }); -}; -``` - -T> Loaders were originally designed to work in synchronous loader pipelines, like Node.js (using [enhanced-require](https://github.com/webpack/enhanced-require)), _and_ asynchronous pipelines, like in webpack. However, since expensive synchronous computations are a bad idea in a single-threaded environment like Node.js, we advise to make your loader asynchronously if possible. Synchronous loaders are ok if the amount of computation is trivial. - - -### "Raw" Loader - -By default, the resource file is converted to a UTF-8 string and passed to the loader. By setting the `raw` flag, the loader will receive the raw `Buffer`. Every loader is allowed to deliver its result as `String` or as `Buffer`. The compiler converts them between loaders. - -__raw-loader.js__ - -``` js -module.exports = function(content) { - assert(content instanceof Buffer); - return someSyncOperation(content); - // return value can be a `Buffer` too - // This is also allowed if loader is not "raw" -}; -module.exports.raw = true; -``` - - -### Pitching Loader - -Loaders are __always__ called from right to left. There are some instances where the loader only cares about the __metadata__ behind a request and can ignore the results of the previous loader. The `pitch` method on loaders is called from __left to right__ before the loaders are actually executed (from right to left). For the following [`use`](/configuration/module#rule-use) configuration: - -``` js -module.exports = { - //... - module: { - rules: [ - { - //... - use: [ - 'a-loader', - 'b-loader', - 'c-loader' - ] - } - ] - } -}; -``` - -These steps would occur: - -``` diff -|- a-loader `pitch` - |- b-loader `pitch` - |- c-loader `pitch` - |- requested module is picked up as a dependency - |- c-loader normal execution - |- b-loader normal execution -|- a-loader normal execution -``` - -So why might a loader take advantage of the "pitching" phase? - -First, the `data` passed to the `pitch` method is exposed in the execution phase as well under `this.data` and could be useful for capturing and sharing information from earlier in the cycle. - -``` js -module.exports = function(content) { - return someSyncOperation(content, this.data.value); -}; - -module.exports.pitch = function(remainingRequest, precedingRequest, data) { - data.value = 42; -}; -``` - -Second, if a loader delivers a result in the `pitch` method the process turns around and skips the remaining loaders. In our example above, if the `b-loader`s `pitch` method returned something: - -``` js -module.exports = function(content) { - return someSyncOperation(content); -}; - -module.exports.pitch = function(remainingRequest, precedingRequest, data) { - if (someCondition()) { - return 'module.exports = require(' + JSON.stringify('-!' + remainingRequest) + ');'; - } -}; -``` - -The steps above would be shortened to: - -``` diff -|- a-loader `pitch` - |- b-loader `pitch` returns a module -|- a-loader normal execution -``` - -See the [bundle-loader](https://github.com/webpack-contrib/bundle-loader) for a good example of how this process can be used in a more meaningful way. - - -## The Loader Context - -The loader context represents the properties that are available inside of a loader assigned to the `this` property. - -Given the following example this require call is used: -In `/abc/file.js`: - -``` js -require('./loader1?xyz!loader2!./resource?rrr'); -``` - - -### `this.version` - -__Loader API version.__ Currently `2`. This is useful for providing backwards compatibility. Using the version you can specify custom logic or fallbacks for breaking changes. - - -### `this.context` - -__The directory of the module.__ Can be used as context for resolving other stuff. - -In the example: `/abc` because `resource.js` is in this directory - - -### `this.rootContext` - -Starting with webpack 4, the formerly `this.options.context` is provided as `this.rootContext`. - - -### `this.request` - -The resolved request string. - -In the example: `"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"` - - -### `this.query` - -1. If the loader was configured with an [`options`](/configuration/module/#useentry) object, this will point to that object. -2. If the loader has no `options`, but was invoked with a query string, this will be a string starting with `?`. - -T> Use the [`getOptions` method](https://github.com/webpack/loader-utils#getoptions) from `loader-utils` to extract given loader options. - - -### `this.callback` - -A function that can be called synchronously or asynchronously in order to return multiple results. The expected arguments are: - -<!-- eslint-skip --> - -```js -this.callback( - err: Error | null, - content: string | Buffer, - sourceMap?: SourceMap, - meta?: any -); -``` - -1. The first argument must be an `Error` or `null` -2. The second argument a `string` or a [`Buffer`](https://nodejs.org/api/buffer.html). -3. Optional: The third argument must be a source map that is parsable by [this module](https://github.com/mozilla/source-map). -4. Optional: The fourth option, ignored by webpack, can be anything (e.g. some meta data). - -T> It can be useful to pass an abstract syntax tree (AST), like [`ESTree`](https://github.com/estree/estree), as the fourth argument (`meta`) to speed up the build time if you want to share common ASTs between loaders. - -In case this function is called, you should return undefined to avoid ambiguous loader results. - - -### `this.async` - -Tells the [loader-runner](https://github.com/webpack/loader-runner) that the loader intends to call back asynchronously. Returns `this.callback`. - - -### `this.data` - -A data object shared between the pitch and the normal phase. - - -### `this.cacheable` - -A function that sets the cacheable flag: - -``` typescript -cacheable(flag = true: boolean) -``` - -By default, loader results are flagged as cacheable. Call this method passing `false` to make the loader's result not cacheable. - -A cacheable loader must have a deterministic result, when inputs and dependencies haven't changed. This means the loader shouldn't have other dependencies than specified with `this.addDependency`. - - -### `this.loaders` - -An array of all the loaders. It is writeable in the pitch phase. - -<!-- eslint-skip --> - -```js -loaders = [{request: string, path: string, query: string, module: function}] -``` - -In the example: - -``` js -[ - { - request: '/abc/loader1.js?xyz', - path: '/abc/loader1.js', - query: '?xyz', - module: [Function] - }, - { - request: '/abc/node_modules/loader2/index.js', - path: '/abc/node_modules/loader2/index.js', - query: '', - module: [Function] - } -]; -``` - - -### `this.loaderIndex` - -The index in the loaders array of the current loader. - -In the example: in loader1: `0`, in loader2: `1` - - -### `this.resource` - -The resource part of the request, including query. - -In the example: `"/abc/resource.js?rrr"` - - -### `this.resourcePath` - -The resource file. - -In the example: `"/abc/resource.js"` - - -### `this.resourceQuery` - -The query of the resource. - -In the example: `"?rrr"` - - -### `this.target` - -Target of compilation. Passed from configuration options. - -Example values: `"web"`, `"node"` - - -### `this.webpack` - -This boolean is set to true when this is compiled by webpack. - -T> Loaders were originally designed to also work as Babel transforms. Therefore if you write a loader that works for both, you can use this property to know if there is access to additional loaderContext and webpack features. - - -### `this.sourceMap` - -Should a source map be generated. Since generating source maps can be an expensive task, you should check if source maps are actually requested. - - -### `this.emitWarning` - -``` typescript -emitWarning(warning: Error) -``` - -Emit a warning. - - -### `this.emitError` - -``` typescript -emitError(error: Error) -``` - -Emit an error. - - -### `this.loadModule` - -``` typescript -loadModule(request: string, callback: function(err, source, sourceMap, module)) -``` - -Resolves the given request to a module, applies all configured loaders and calls back with the generated source, the sourceMap and the module instance (usually an instance of [`NormalModule`](https://github.com/webpack/webpack/blob/master/lib/NormalModule.js)). Use this function if you need to know the source code of another module to generate the result. - - -### `this.resolve` - -``` typescript -resolve(context: string, request: string, callback: function(err, result: string)) -``` - -Resolve a request like a require expression. - - -### `this.addDependency` - -``` typescript -addDependency(file: string) -dependency(file: string) // shortcut -``` - -Adds a file as dependency of the loader result in order to make them watchable. For example, [`html-loader`](https://github.com/webpack-contrib/html-loader) uses this technique as it finds `src` and `src-set` attributes. Then, it sets the url's for those attributes as dependencies of the html file that is parsed. - - -### `this.addContextDependency` - -``` typescript -addContextDependency(directory: string) -``` - -Add a directory as dependency of the loader result. - - -### `this.clearDependencies` - -``` typescript -clearDependencies() -``` - -Remove all dependencies of the loader result. Even initial dependencies and these of other loaders. Consider using `pitch`. - - -### `this.emitFile` - -``` typescript -emitFile(name: string, content: Buffer|string, sourceMap: {...}) -``` - -Emit a file. This is webpack-specific. - - -### `this.fs` - -Access to the `compilation`'s `inputFileSystem` property. - - -## Deprecated context properties - -W> The usage of these properties is highly discouraged since we are planning to remove them from the context. They are still listed here for documentation purposes. - - -### `this.exec` - -``` typescript -exec(code: string, filename: string) -``` - -Execute some code fragment like a module. See [this comment](https://github.com/webpack/webpack.js.org/issues/1268#issuecomment-313513988) for a replacement method if needed. - - -### `this.resolveSync` - -``` typescript -resolveSync(context: string, request: string) -> string -``` - -Resolve a request like a require expression. - - -### `this.value` - -Pass values to the next loader. If you know what your result exports if executed as module, set this value here (as a only element array). - - -### `this.inputValue` - -Passed from the last loader. If you would execute the input argument as module, consider reading this variable for a shortcut (for performance). - - -### `this.options` - -W> The `options` property has been deprecated in webpack 3 and removed in webpack 4. - - -### `this.debug` - -A boolean flag. It is set when in debug mode. - - -### `this.minimize` - -Should the result be minimized. - - -### `this._compilation` - -Hacky access to the Compilation object of webpack. - - -### `this._compiler` - -Hacky access to the Compiler object of webpack. - - -### `this._module` - -Hacky access to the Module object being loaded. - - -# Module Variables - -This section covers all __variables__ available in code compiled with webpack. Modules will have access to certain data from the compilation process through `module` and other variables. - - -### `module.loaded` (NodeJS) - -This is `false` if the module is currently executing, and `true` if the sync execution has finished. - - -### `module.hot` (webpack-specific) - -Indicates whether or not [Hot Module Replacement](/concepts/hot-module-replacement) is enabled and provides an interface to the process. See the [HMR API page](/api/hot-module-replacement) for details. - - -### `module.id` (CommonJS) - -The ID of the current module. - -``` javascript -module.id === require.resolve('./file.js'); -``` - - -### `module.exports` (CommonJS) - -Defines the value that will be returned when a consumer makes a `require` call to the module (defaults to a new object). - -``` javascript -module.exports = function doSomething() { - // Do something... -}; -``` - -W> This CANNOT be used in an asynchronous function. - - -### `exports` (CommonJS) - -This variable is equal to default value of `module.exports` (i.e. an object). If `module.exports` gets overwritten, `exports` will no longer be exported. - -``` javascript -exports.someValue = 42; -exports.anObject = { - x: 123 -}; -exports.aFunction = function doSomething() { - // Do something -}; -``` - - -### `global` (NodeJS) - -See [node.js global](https://nodejs.org/api/globals.html#globals_global). - - -### `process` (NodeJS) - -See [node.js process](https://nodejs.org/api/process.html). - - -### `__dirname` (NodeJS) - -Depending on the config option `node.__dirname`: - -- `false`: Not defined -- `mock`: equal "/" -- `true`: [node.js __dirname](https://nodejs.org/api/globals.html#globals_dirname) - -If used inside a expression that is parsed by the Parser, the config option is treated as `true`. - - -### `__filename` (NodeJS) - -Depending on the config option `node.__filename`: - -- `false`: Not defined -- `mock`: equal "/index.js" -- `true`: [node.js __filename](https://nodejs.org/api/globals.html#globals_filename) - -If used inside a expression that is parsed by the Parser, the config option is treated as `true`. - - -### `__resourceQuery` (webpack-specific) - -The resource query of the current module. If the following `require` call were made, then the query string would be available in `file.js`. - -``` javascript -require('file.js?test'); -``` - -__file.js__ - -``` javascript -__resourceQuery === '?test'; -``` - - -### `__webpack_public_path__` (webpack-specific) - -Equals the config options `output.publicPath`. - - -### `__webpack_require__` (webpack-specific) - -The raw require function. This expression isn't parsed by the Parser for dependencies. - - -### `__webpack_chunk_load__` (webpack-specific) - -The internal chunk loading function. Takes two arguments: - -- `chunkId` The id for the chunk to load. -- `callback(require)` A callback function called once the chunk is loaded. - - -### `__webpack_modules__` (webpack-specific) - -Access to the internal object of all modules. - - -### `__webpack_hash__` (webpack-specific) - -This variable is only available with the `HotModuleReplacementPlugin` or the `ExtendedAPIPlugin`. It provides access to the hash of the compilation. - - -### `__non_webpack_require__` (webpack-specific) - -Generates a `require` function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available. - - -### `DEBUG` (webpack-specific) - -Equals the config option `debug`. - - -# Parser - -The `parser` instance, found in the `compiler`, is used to parse each module -being processed by webpack. The `parser` is yet another webpack class that -extends `tapable` and provides a variety of `tapable` hooks that can be used by -plugin authors to customize the parsing process. - -The `parser` is found within [module factories](/api/compiler-hooks/#normalmodulefactory) and therefore takes little -more work to access: - -``` js -compiler.hooks.normalModuleFactory.tap('MyPlugin', factory => { - factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => { - parser.hooks.someHook.tap(/* ... */); - }); -}); -``` - -As with the `compiler`, `tapAsync` and `tapPromise` may also be available -depending on the type of hook. - - -## Hooks - -The following lifecycle hooks are exposed by the `parser` and can be accessed -as such: - - -### evaluateTypeof - -`SyncBailHook` - -Evaluate the type of an identifier. - -Parameters: `expression` - - -### evaluate - -`SyncBailHook` - -Evaluate an expression. - -Parameters: `expression` - - -### evaluateIdentifier - -`SyncBailHook` - -Evaluate an identifier that is a free variable. - -Parameters: `expression` - - -### evaluateDefinedIdentifier - -`SyncBailHook` - -Evaluate an identifier that is a defined variable. - -Parameters: `expression` - - -### evaluateCallExpressionMember - -`SyncBailHook` - -Evaluate a call to a member function of a successfully evaluated expression. - -Parameters: `expression` `param` - - -### statement - -`SyncBailHook` - -General purpose hook that is called when parsing statements in a code fragment. - -Parameters: `statement` - - -### statementIf - -`SyncBailHook` - -... - -Parameters: `statement` - - -### label - -`SyncBailHook` - -... - -Parameters: `statement` - - -### import - -`SyncBailHook` - -... - -Parameters: `statement` `source` - - -### importSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `source` `exportName` `identifierName` - - -### export - -`SyncBailHook` - -... - -Parameters: `statement` - - -### exportImport - -`SyncBailHook` - -... - -Parameters: `statement` `source` - - -### exportDeclaration - -`SyncBailHook` - -... - -Parameters: `statement` `declaration` - - -### exportExpression - -`SyncBailHook` - -... - -Parameters: `statement` `declaration` - - -### exportSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `identifierName` `exportName` `index` - - -### exportImportSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `source` `identifierName` `exportName` `index` - - -### varDeclaration - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationLet - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationConst - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationVar - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### canRename - -`SyncBailHook` - -... - -Parameters: `initExpression` - - -### rename - -`SyncBailHook` - -... - -Parameters: `initExpression` - - -### assigned - -`SyncBailHook` - -... - -Parameters: `expression` - - -### assign - -`SyncBailHook` - -... - -Parameters: `expression` - - -### typeof - -`SyncBailHook` - -... - -Parameters: `expression` - - -### call - -`SyncBailHook` - -... - -Parameters: `expression` - - -### callAnyMember - -`SyncBailHook` - -... - -Parameters: `expression` - - -### new - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expression - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expressionAnyMember - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expressionConditionalOperator - -`SyncBailHook` - -... - -Parameters: `expression` - - -### program - -`SyncBailHook` - -Get access to the abstract syntax tree (AST) of a code fragment - -Parameters: `ast` `comments` diff --git a/src/content/concepts/_concepts_all.md b/src/content/concepts/_concepts_all.md deleted file mode 100644 index 7ea61cfe8aaa..000000000000 --- a/src/content/concepts/_concepts_all.md +++ /dev/null @@ -1,1086 +0,0 @@ - - -# Concepts - -At its core, __webpack__ is a _static module bundler_ for modern JavaScript applications. When webpack processes your application, it internally builds a [dependency graph](/concepts/dependency-graph/) which maps every module your project needs and generates one or more _bundles_. - -T> Learn more about JavaScript modules and webpack modules [here](/concepts/modules). - -Since version 4.0.0, __webpack does not require a configuration file__ to bundle your project, nevertheless it is [incredibly configurable](/configuration) to better fit your needs. - -To get started you only need to understand its __Core Concepts__: - -- [Entry](#entry) -- [Output](#output) -- [Loaders](#loaders) -- [Plugins](#plugins) -- [Mode](#mode) -- [Browser Compatibility](#browser-compatibility) - -This document is intended to give a __high-level__ overview of these concepts, while providing links to detailed concept specific use cases. - -For a better understanding of the ideas behind module bundlers and how they work under the hood consult these resources: - -- [Manually Bundling an Application](https://www.youtube.com/watch?v=UNMkLHzofQI) -- [Live Coding a Simple Module Bundler](https://www.youtube.com/watch?v=Gc9-7PBqOC8) -- [Detailed Explanation of a Simple Module Bundler](https://github.com/ronami/minipack) - - -## Entry - -An __entry point__ indicates which module webpack should use to begin building out its internal [dependency graph](/concepts/dependency-graph/). webpack will figure out which other modules and libraries that entry point depends on (directly and indirectly). - -By default its value is `./src/index.js`, but you can specify a different (or multiple entry points) by configuring the __entry__ property in the [webpack configuration](/configuration). For example: - -__webpack.config.js__ - -``` js -module.exports = { - entry: './path/to/my/entry/file.js' -}; -``` - -T> Learn more in the [entry points](/concepts/entry-points) section. - - -## Output - -The __output__ property tells webpack where to emit the _bundles_ it creates and how to name these files. It defaults to `./dist/main.js` for the main output file and to the `./dist` folder for any other generated file. - -You can configure this part of the process by specifying an `output` field in your configuration: - -__webpack.config.js__ - -```javascript -const path = require('path'); - -module.exports = { - entry: './path/to/my/entry/file.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'my-first-webpack.bundle.js' - } -}; -``` - -In the example above, we use the `output.filename` and the `output.path` properties to tell webpack the name of our bundle and where we want it to be emitted to. In case you're wondering about the path module being imported at the top, it is a core [Node.js module](https://nodejs.org/api/modules.html) that gets used to manipulate file paths. - -T> The `output` property has [many more configurable features](/configuration/output) and if you like to know more about the concepts behind it, you can [read more in the output section](/concepts/output). - - -## Loaders - -Out of the box, webpack only understands JavaScript and JSON files. __Loaders__ allow webpack to process other types of files and convert them into valid [modules](/concepts/modules) that can be consumed by your application and added to the dependency graph. - -W> Note that the ability to `import` any type of module, e.g. `.css` files, is a feature specific to webpack and may not be supported by other bundlers or task runners. We feel this extension of the language is warranted as it allows developers to build a more accurate dependency graph. - -At a high level, __loaders__ have two properties in your webpack configuration: - -1. The `test` property identifies which file or files should be transformed. -2. The `use` property indicates which loader should be used to do the transforming. - -__webpack.config.js__ - -```javascript -const path = require('path'); - -module.exports = { - output: { - filename: 'my-first-webpack.bundle.js' - }, - module: { - rules: [ - { test: /\.txt$/, use: 'raw-loader' } - ] - } -}; -``` - -The configuration above has defined a `rules` property for a single module with two required properties: `test` and `use`. This tells webpack's compiler the following: - -> "Hey webpack compiler, when you come across a path that resolves to a '.txt' file inside of a `require()`/`import` statement, __use__ the `raw-loader` to transform it before you add it to the bundle." - -W> It is important to remember that when defining rules in your webpack config, you are defining them under `module.rules` and not `rules`. For your benefit, webpack will warn you if this is done incorrectly. - -You can check further customization when including loaders in the [loaders section](/concepts/loaders). - - -## Plugins - -While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables. - -T> Check out the [plugin interface](/api/plugins) and how to use it to extend webpacks capabilities. - -In order to use a plugin, you need to `require()` it and add it to the `plugins` array. Most plugins are customizable through options. Since you can use a plugin multiple times in a config for different purposes, you need to create an instance of it by calling it with the `new` operator. - -__webpack.config.js__ - -```javascript -const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm -const webpack = require('webpack'); //to access built-in plugins - -module.exports = { - module: { - rules: [ - { test: /\.txt$/, use: 'raw-loader' } - ] - }, - plugins: [ - new HtmlWebpackPlugin({template: './src/index.html'}) - ] -}; -``` - -In the example above, the `html-webpack-plugin` generates an HTML file for your application by injecting automatically all your generated bundles. - -T> There are many plugins that webpack provides out of the box! Check out the [list of plugins](/plugins). - -Using plugins in your webpack config is straightforward - however, there are many use cases that are worth further exploration. [Learn more about them here](/concepts/plugins). - - -## Mode - -By setting the `mode` parameter to either `development`, `production` or `none`, you can enable webpack's built-in optimizations that correspond to each environment. The default value is `production`. - -```javascript -module.exports = { - mode: 'production' -}; -``` - -Learn more about the [mode configuration here](/concepts/mode) and what optimizations take place on each value. - - -## Browser Compatibility - -webpack supports all browsers that are [ES5-compliant](https://kangax.github.io/compat-table/es5/) (IE8 and below are not supported). webpack needs `Promise` for `import()` and `require.ensure()`. If you want to support older browsers, you will need to [load a polyfill](/guides/shimming/) before using these expressions. - - -# Entry Points - -As mentioned in [Getting Started](/guides/getting-started/#using-a-configuration), there are multiple ways to define the `entry` property in your webpack configuration. We will show you the ways you __can__ configure the `entry` property, in addition to explaining why it may be useful to you. - - -## Single Entry (Shorthand) Syntax - -Usage: `entry: string|Array<string>` - -__webpack.config.js__ - -```javascript -module.exports = { - entry: './path/to/my/entry/file.js' -}; -``` - -The single entry syntax for the `entry` property is a shorthand for: - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - main: './path/to/my/entry/file.js' - } -}; -``` - -T> __What happens when you pass an array to `entry`?__ Passing an array of file paths to the `entry` property creates what is known as a __"multi-main entry"__. This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk". - -This is a great choice when you are looking to quickly setup a webpack configuration for an application or tool with one entry point (i.e., a library). However, there is not much flexibility in extending or scaling your configuration with this syntax. - - -## Object Syntax - -Usage: `entry: {[entryChunkName: string]: string|Array<string>}` - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - app: './src/app.js', - adminApp: './src/adminApp.js' - } -}; -``` - -The object syntax is more verbose. However, this is the most scalable way of defining entry/entries in your application. - -T> __"Scalable webpack configurations"__ are ones that can be reused and combined with other partial configurations. This is a popular technique used to separate concerns by environment, build target and runtime. They are then merged using specialized tools like [webpack-merge](https://github.com/survivejs/webpack-merge). - - -## Scenarios - -Below is a list of entry configurations and their real-world use cases: - -### Separate App and Vendor Entries - -T> In webpack version < 4 it was common to add vendors as separate entrypoint to compile it as separate file (in combination with the `CommonsChunkPlugin`). This is discouraged in webpack 4. Instead the `optimization.splitChunks` option takes care of separating vendors and app modules and creating a separate file. __Do not__ create a entry for vendors or other stuff which is not the starting point of execution. - -### Multi Page Application - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - pageOne: './src/pageOne/index.js', - pageTwo: './src/pageTwo/index.js', - pageThree: './src/pageThree/index.js' - } -}; -``` - -__What does this do?__ We are telling webpack that we would like 3 separate dependency graphs (like the above example). - -__Why?__ In a multi-page application, the server is going to fetch a new HTML document for you. The page reloads this new document and assets are redownloaded. However, this gives us the unique opportunity to do multiple things: - -- Use `optimization.splitChunks` to create bundles of shared application code between each page. Multi-page applications that reuse a lot of code/modules between entry points can greatly benefit from these techniques, as the amount of entry points increase. - -T> As a rule of thumb: for each HTML document use exactly one entry point. - - -# Output - -Configuring the `output` configuration options tells webpack how to write the compiled files to disk. Note that, while there can be multiple `entry` points, only one `output` configuration is specified. - - -## Usage - -The minimum requirements for the `output` property in your webpack config is to set its value to an object including the following thing: - -- A `filename` to use for the output file(s). - -__webpack.config.js__ - -```javascript -module.exports = { - output: { - filename: 'bundle.js', - } -}; -``` - -This configuration would output a single `bundle.js` file into the `dist` directory. - - -## Multiple Entry Points - -If your configuration creates more than a single "chunk" (as with multiple entry points or when using plugins like CommonsChunkPlugin), you should use [substitutions](/configuration/output#output-filename) to ensure that each file has a unique name. - -```javascript -module.exports = { - entry: { - app: './src/app.js', - search: './src/search.js' - }, - output: { - filename: '[name].js', - path: __dirname + '/dist' - } -}; - -// writes to disk: ./dist/app.js, ./dist/search.js -``` - - -## Advanced - -Here's a more complicated example of using a CDN and hashes for assets: - -__config.js__ - -```javascript -module.exports = { - //... - output: { - path: '/home/proj/cdn/assets/[hash]', - publicPath: 'http://cdn.example.com/assets/[hash]/' - } -}; -``` - -In cases where the eventual `publicPath` of output files isn't known at compile time, it can be left blank and set dynamically at runtime via the `__webpack_public_path__` variable in the entry point file: - -```javascript -__webpack_public_path__ = myRuntimePublicPath; - -// rest of your application entry -``` - - -# Loaders - -Loaders are transformations that are applied on the source code of a module. They allow you to pre-process files as you `import` or “load” them. Thus, loaders are kind of like “tasks” in other build tools and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript or inline images as data URLs. Loaders even allow you to do things like `import` CSS files directly from your JavaScript modules! - - -## Example - -For example, you can use loaders to tell webpack to load a CSS file or to convert TypeScript to JavaScript. To do this, you would start by installing the loaders you need: - -``` bash -npm install --save-dev css-loader -npm install --save-dev ts-loader -``` - -And then instruct webpack to use the [`css-loader`](/loaders/css-loader) for every `.css` file and the [`ts-loader`](https://github.com/TypeStrong/ts-loader) for all `.ts` files: - -__webpack.config.js__ - -``` js -module.exports = { - module: { - rules: [ - { test: /\.css$/, use: 'css-loader' }, - { test: /\.ts$/, use: 'ts-loader' } - ] - } -}; -``` - - -## Using Loaders - -There are three ways to use loaders in your application: - -- [Configuration](#configuration) (recommended): Specify them in your __webpack.config.js__ file. -- [Inline](#inline): Specify them explicitly in each `import` statement. -- [CLI](#cli): Specify them within a shell command. - - -### Configuration - -[`module.rules`](/configuration/module/#module-rules) allows you to specify several loaders within your webpack configuration. -This is a concise way to display loaders, and helps to maintain clean code. It also offers you a full overview of each respective loader. - -Loaders are evaluated/executed from right to left. In the example below execution starts with sass-loader, continues with css-loader and finally ends with style-loader. See ["Loader Features"](/concepts/loaders/#loader-features) for more information about loaders order. - -```js-with-links-with-details -module.exports = { - module: { - rules: [ - { - test: /\.css$/, - use: [ - { loader: ['style-loader'](/loaders/style-loader) }, - { - loader: ['css-loader'](/loaders/css-loader), - options: { - modules: true - } - }, - { loader: ['sass-loader'](/loaders/sass-loader) } - ] - } - ] - } -}; -``` - - -### Inline - -It's possible to specify loaders in an `import` statement, or any [equivalent "importing" method](/api/module-methods). Separate loaders from the resource with `!`. Each part is resolved relative to the current directory. - -```js -import Styles from 'style-loader!css-loader?modules!./styles.css'; -``` - -It's possible to override any loaders in the configuration by prefixing the entire rule with `!`. - -Options can be passed with a query parameter, e.g. `?key=value&foo=bar`, or a JSON object, e.g. `?{"key":"value","foo":"bar"}`. - -T> Use `module.rules` whenever possible, as this will reduce boilerplate in your source code and allow you to debug or locate a loader faster if something goes south. - - -### CLI - -You can also use loaders through the CLI: - -```sh -webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader' -``` - -This uses the `jade-loader` for `.jade` files, and the [`style-loader`](/loaders/style-loader) and [`css-loader`](/loaders/css-loader) for `.css` files. - - -## Loader Features - -- Loaders can be chained. Each loader in the chain applies transformations to the processed resource. A chain is executed in reverse order. The first loader passes its result (resource with applied transformations) to the next one, and so forth. Finally, webpack expects JavaScript to be returned by the last loader in the chain. -- Loaders can be synchronous or asynchronous. -- Loaders run in Node.js and can do everything that’s possible there. -- Loaders can be configured with an `options` object (using `query` parameters to set options is still supported but has been deprecated). -- Normal modules can export a loader in addition to the normal `main` via `package.json` with the `loader` field. -- Plugins can give loaders more features. -- Loaders can emit additional arbitrary files. - -Loaders allow more power in the JavaScript ecosystem through preprocessing -functions (loaders). Users now have more flexibility to include fine-grained logic such as compression, packaging, language translations and [more](/loaders). - - -## Resolving Loaders - -Loaders follow the standard [module resolution](/concepts/module-resolution/). In most cases it will be loaded from the [module path](/concepts/module-resolution/#module-paths) (think `npm install`, `node_modules`). - -A loader module is expected to export a function and be written in Node.js compatible JavaScript. They are most commonly managed with npm, but you can also have custom loaders as files within your application. By convention, loaders are usually named `xxx-loader` (e.g. `json-loader`). See ["How to Write a Loader?"](/development/how-to-write-a-loader) for more information. - - -# Mode - -Providing the `mode` configuration option tells webpack to use its built-in optimizations accordingly. - -`string` - -T> Possible values for `mode` are: `none`, `development` or `production`(default). - -## Usage - -Just provide the `mode` option in the config: - -```javascript -module.exports = { - mode: 'production' -}; -``` - - -or pass it as a [CLI](/api/cli/) argument: - -```bash -webpack --mode=production -``` - -The following string values are supported: - -Option | Description ---------------------- | ----------------------- -`development` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `development`. Enables `NamedChunksPlugin` and `NamedModulesPlugin`. -`production` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `production`. Enables `FlagDependencyUsagePlugin`, `FlagIncludedChunksPlugin`, `ModuleConcatenationPlugin`, `NoEmitOnErrorsPlugin`, `OccurrenceOrderPlugin`, `SideEffectsFlagPlugin` and `TerserPlugin`. -`none` | Opts out of any default optimization options - -If not set, webpack sets `production` as the default value for `mode`. The supported values for mode are: - -T> Please remember that setting `NODE_ENV` doesn't automatically set `mode`. - - -### Mode: development - - -```diff -// webpack.development.config.js -module.exports = { -+ mode: 'development' -- devtool: 'eval', -- cache: true, -- performance: { -- hints: false -- }, -- output: { -- pathinfo: true -- }, -- optimization: { -- namedModules: true, -- namedChunks: true, -- nodeEnv: 'development', -- flagIncludedChunks: false, -- occurrenceOrder: false, -- sideEffects: false, -- usedExports: false, -- concatenateModules: false, -- splitChunks: { -- hidePathInfo: false, -- minSize: 10000, -- maxAsyncRequests: Infinity, -- maxInitialRequests: Infinity, -- }, -- noEmitOnErrors: false, -- checkWasmTypes: false, -- minimize: false, -- }, -- plugins: [ -- new webpack.NamedModulesPlugin(), -- new webpack.NamedChunksPlugin(), -- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), -- ] -} -``` - - -### Mode: production - - -```diff -// webpack.production.config.js -module.exports = { -+ mode: 'production', -- performance: { -- hints: 'warning' -- }, -- output: { -- pathinfo: false -- }, -- optimization: { -- namedModules: false, -- namedChunks: false, -- nodeEnv: 'production', -- flagIncludedChunks: true, -- occurrenceOrder: true, -- sideEffects: true, -- usedExports: true, -- concatenateModules: true, -- splitChunks: { -- hidePathInfo: true, -- minSize: 30000, -- maxAsyncRequests: 5, -- maxInitialRequests: 3, -- }, -- noEmitOnErrors: true, -- checkWasmTypes: true, -- minimize: true, -- }, -- plugins: [ -- new TerserPlugin(/* ... */), -- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), -- new webpack.optimize.ModuleConcatenationPlugin(), -- new webpack.NoEmitOnErrorsPlugin() -- ] -} -``` - - -### Mode: none - - -```diff -// webpack.custom.config.js -module.exports = { -+ mode: 'none', -- performance: { -- hints: false -- }, -- optimization: { -- flagIncludedChunks: false, -- occurrenceOrder: false, -- sideEffects: false, -- usedExports: false, -- concatenateModules: false, -- splitChunks: { -- hidePathInfo: false, -- minSize: 10000, -- maxAsyncRequests: Infinity, -- maxInitialRequests: Infinity, -- }, -- noEmitOnErrors: false, -- checkWasmTypes: false, -- minimize: false, -- }, -- plugins: [] -} -``` - -If you want to change the behavior according to the __mode__ variable inside the _webpack.config.js_, you have to export a function instead of an object: - -```javascript -var config = { - entry: './app.js' - //... -}; - -module.exports = (env, argv) => { - - if (argv.mode === 'development') { - config.devtool = 'source-map'; - } - - if (argv.mode === 'production') { - //... - } - - return config; -}; -``` - - -# Plugins - -__Plugins__ are the [backbone](https://github.com/webpack/tapable) of webpack. webpack itself is built on the __same plugin system__ that you use in your webpack configuration! - -They also serve the purpose of doing __anything else__ that a [loader](/concepts/loaders) cannot do. - - -## Anatomy - -A webpack __plugin__ is a JavaScript object that has an [`apply`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) method. This `apply` method is called by the webpack compiler, giving access to the __entire__ compilation lifecycle. - -__ConsoleLogOnBuildWebpackPlugin.js__ - -```javascript -const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; - -class ConsoleLogOnBuildWebpackPlugin { - apply(compiler) { - compiler.hooks.run.tap(pluginName, compilation => { - console.log('The webpack build process is starting!!!'); - }); - } -} -``` - -The first parameter of the tap method of the compiler hook should be a camelized version of the plugin name. It is advisable to use a constant for this so it can be reused in all hooks. - -## Usage - -Since __plugins__ can take arguments/options, you must pass a `new` instance to the `plugins` property in your webpack configuration. - -Depending on how you are using webpack, there are multiple ways to use plugins. - - -### Configuration - -__webpack.config.js__ - -```javascript -const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm -const webpack = require('webpack'); //to access built-in plugins -const path = require('path'); - -module.exports = { - entry: './path/to/my/entry/file.js', - output: { - filename: 'my-first-webpack.bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.(js|jsx)$/, - use: 'babel-loader' - } - ] - }, - plugins: [ - new webpack.ProgressPlugin(), - new HtmlWebpackPlugin({template: './src/index.html'}) - ] -}; -``` - - -### Node API - -When using the Node API, you can also pass plugins via the `plugins` property in the configuration. - -__some-node-script.js__ - -```javascript -const webpack = require('webpack'); //to access webpack runtime -const configuration = require('./webpack.config.js'); - -let compiler = webpack(configuration); - -new webpack.ProgressPlugin().apply(compiler); - -compiler.run(function(err, stats) { - // ... -}); -``` - -T> Did you know: The example seen above is extremely similar to the [webpack runtime itself!](https://github.com/webpack/webpack/blob/e7087ffeda7fa37dfe2ca70b5593c6e899629a2c/bin/webpack.js#L290-L292) There are lots of great usage examples hiding in the [webpack source code](https://github.com/webpack/webpack) that you can apply to your own configurations and scripts! - - -# Configuration - -You may have noticed that few webpack configurations look exactly alike. This is because __webpack's configuration file is a JavaScript file that exports a webpack [configuration](/configuration/).__ This configuration is then processed by webpack based upon its defined properties. - -Because it's a standard Node.js CommonJS module, you __can do the following__: - -- import other files via `require(...)` -- use utilities on npm via `require(...)` -- use JavaScript control flow expressions i. e. the `?:` operator -- use constants or variables for often used values -- write and execute functions to generate a part of the configuration - -Use these features when appropriate. - -While they are technically feasible, __the following practices should be avoided__: - -- Access CLI arguments, when using the webpack CLI (instead write your own CLI, or [use `--env`](/configuration/configuration-types/)) -- Export non-deterministic values (calling webpack twice should result in the same output files) -- Write long configurations (instead split the configuration into multiple files) - -T> The most important part to take away from this document is that there are many different ways to format and style your webpack configuration. The key is to stick with something consistent that you and your team can understand and maintain. - -The examples below describe how webpack's configuration can be both expressive and configurable because _it is code_: - -## Simple Configuration - -__webpack.config.js__ - -```javascript -var path = require('path'); - -module.exports = { - mode: 'development', - entry: './foo.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'foo.bundle.js' - } -}; -``` - -_See_: [Configuration section](/configuration/) for the all supported configuration options - -## Multiple Targets - -Along with exporting a single configuration as an object, [function](/configuration/configuration-types/#exporting-a-function) or [Promise](/configuration/configuration-types/#exporting-a-promise), you can export multiple configurations. - -_See_: [Exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) - -## Using other Configuration Languages - -webpack accepts configuration files written in multiple programming and data languages. - -_See_: [Configuration Languages](/configuration/configuration-languages/) - - -# Modules - -In [modular programming](https://en.wikipedia.org/wiki/Modular_programming), developers break programs up into discrete chunks of functionality called a _module_. - -Each module has a smaller surface area than a full program, making verification, debugging, and testing trivial. -Well-written _modules_ provide solid abstractions and encapsulation boundaries, so that each module has a coherent design and a clear purpose within the overall application. - -Node.js has supported modular programming almost since its inception. -On the web, however, support for _modules_ has been slow to arrive. -Multiple tools exist that support modular JavaScript on the web, with a variety of benefits and limitations. -webpack builds on lessons learned from these systems and applies the concept of _modules_ to any file in your project. - -## What is a webpack Module - -In contrast to [Node.js modules](https://nodejs.org/api/modules.html), webpack _modules_ can express their _dependencies_ in a variety of ways. A few examples are: - -- An [ES2015 `import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) statement -- A [CommonJS](http://www.commonjs.org/specs/modules/1.0/) `require()` statement -- An [AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md) `define` and `require` statement -- An [`@import` statement](https://developer.mozilla.org/en-US/docs/Web/CSS/@import) inside of a css/sass/less file. -- An image url in a stylesheet (`url(...)`) or html (`<img src=...>`) file. - -T> webpack 1 requires a specific loader to convert ES2015 `import`, however this is possible out of the box via webpack 2 - -## Supported Module Types - -webpack supports modules written in a variety of languages and preprocessors, via _loaders_. _Loaders_ describe to webpack __how__ to process non-JavaScript _modules_ and include these _dependencies_ into your _bundles_. -The webpack community has built _loaders_ for a wide variety of popular languages and language processors, including: - -- [CoffeeScript](http://coffeescript.org) -- [TypeScript](https://www.typescriptlang.org) -- [ESNext (Babel)](https://babeljs.io) -- [Sass](http://sass-lang.com) -- [Less](http://lesscss.org) -- [Stylus](http://stylus-lang.com) - -And many others! Overall, webpack provides a powerful and rich API for customization that allows one to use webpack for __any stack__, while staying __non-opinionated__ about your development, testing, and production workflows. - -For a full list, see [__the list of loaders__](/loaders) or [__write your own__](/api/loaders). - - -# Why webpack - -To understand why you should use webpack let's do a recap of how we used JavaScript on the web before bundlers were a thing. - -There are two ways to run JavaScript in a browser. First, include a script for each functionality you want to implement, the issue is that the solution is hard to scale as loading too many scripts causes a network bottleneck. The other alternative is to load a big .js file containing all your project code, but this results in an unmaintainable scripts that causes problems in scope, size, readability, fragility and monolith files. - - -## IIFE's - Immediately invoked function expressions - -IIFEs solve scoping issues for large projects. When script files are wrapped by an IIFE, you can safely concatenate or safely combine files without concern of scope collision. - -This lead to tools like Make, Gulp, Grunt, Broccoli or Brunch. These tools are known as task runners and they are used, among other purposes, to concatenate all your project files together in order to solve some of the issues mentioned before. - -However, anytime you want to change one file you have to rebuild the whole thing. Concatenating makes it trivial to reuse scripts across files and makes build optimizations more difficult to implement. How do you even know what code is being used and which is not? - -If you are only using one function from lodash or one date utility from moment.js you are actually adding the entire library and just squishing it together. How do you treeshake the dependencies on your code? Also, lazy loading chunks of code can be hard to achieve at scale and requires a lot of manual work from the developer. - - -## Birth of JavaScript Modules happened thanks to Node.js - -webpack runs on Node.js, a JavaScript runtime that can be used in computers and servers outside a browser environment. - -When Node.js was released a new era started, and it came with new challenges. Now that JavaScript is not running in a browser, how are Node applications supposed to load new chunks of code? There are no html files and script tags that can be added to it. - -CommonJS came out and introduced `require`, which allows you to load and use a module in the current file. This solves scope issues out of the box and which code is used becomes clear since we need to import each module that we are going to need. - - -## npm + Node.js + modules -- mass distribution - -JavaScript is taking over the world as a language, as a platform and as a way to rapidly develop and create fast running applications. - -But there is no browser support for CommonJS. There are no [live bindings](https://medium.com/webpack/the-state-of-javascript-modules-4636d1774358). There are problems with circular references. Sync module resolution loader is slow. While CommonJS was a great solution for Node.js projects, browsers didn't support modules. That's when bundlers and tools like Browserify, RequireJS and SystemJS were created to solve this limitation making it possible to write CommonJS modules that run in a browser. - - -## ESM - ECMAScript Modules - -The good news for web projects is that modules are becoming an official feature in ECMAScript standard, though browser support is still short and early implementations show that bundling is still faster and recommended today. - - -## Wouldn't it be nice… - -...to have something that will not only let us write modules but also support any module format (at least until we get to ESM) and that can handle resources and assets at the same time? - -This is why webpack exists. It's a tool that not only let's you bundle your JavaScript applications, supporting both ESM and CommonJS, but can be extended to support all different kinds of assets like images, fonts and stylesheets. - -webpack cares a lot about performance and it's always adding and improving features like async chunk loading and prefetching to help you deliver the best possible version of your project to the user, always caring about loading times and performance. - - -# Module Resolution - -A resolver is a library which helps in locating a module by its absolute path. -A module can be required as a dependency from another module as: - -```js -import foo from 'path/to/module'; -// or -require('path/to/module'); -``` - -The dependency module can be from the application code or a third party library. The resolver helps -webpack find the module code that needs to be included in the bundle for every such `require`/`import` statement. -webpack uses [enhanced-resolve](https://github.com/webpack/enhanced-resolve) to resolve file paths while bundling modules. - - -## Resolving rules in webpack - -Using `enhanced-resolve`, webpack can resolve three kinds of file paths: - - -### Absolute paths - -```js -import '/home/me/file'; - -import 'C:\\Users\\me\\file'; -``` - -Since we already have the absolute path to the file, no further resolution is required. - - -### Relative paths - -```js -import '../src/file1'; -import './file2'; -``` - -In this case, the directory of the resource file where the `import` or `require` occurs is taken to be the context directory. The relative path specified in the `import/require` is joined to this context path to produce the absolute path to the module. - - -### Module paths - -```js -import 'module'; -import 'module/lib/file'; -``` - -Modules are searched for inside all directories specified in [`resolve.modules`](/configuration/resolve/#resolve-modules). -You can replace the original module path by an alternate path by creating an alias for it using [`resolve.alias`](/configuration/resolve/#resolve-alias) configuration option. - -Once the path is resolved based on the above rule, the resolver checks to see if the path points to a file or a directory. If the path points to a file: - -- If the path has a file extension, then the file is bundled straightaway. -- Otherwise, the file extension is resolved using the [`resolve.extensions`](/configuration/resolve/#resolve-extensions) option, which tells the resolver which extensions (eg - `.js`, `.jsx`) are acceptable for resolution. - -If the path points to a folder, then the following steps are taken to find the right file with the right extension: - -- If the folder contains a `package.json` file, then fields specified in [`resolve.mainFields`](/configuration/resolve/#resolve-mainfields) configuration option are looked up in order, and the first such field in `package.json` determines the file path. -- If there is no `package.json` or if the main fields do not return a valid path, file names specified in the [`resolve.mainFiles`](/configuration/resolve/#resolve-mainfiles) configuration option are looked for in order, to see if a matching filename exists in the imported/required directory . -- The file extension is then resolved in a similar way using the `resolve.extensions` option. - -webpack provides reasonable [defaults](/configuration/resolve) for these options depending on your build target. - - -## Resolving Loaders - -This follows the same rules as those specified for file resolution. But the [`resolveLoader`](/configuration/resolve/#resolveloader) configuration option can be used to have separate resolution rules for loaders. - - -## Caching - -Every filesystem access is cached, so that multiple parallel or serial requests to the same file occur faster. In [watch mode](/configuration/watch/#watch), only modified files are evicted from the cache. If watch mode is off, then the cache gets purged before every compilation. - - -See [Resolve API](/configuration/resolve) to learn more on the configuration options mentioned above. - - -# Dependency Graph - -Any time one file depends on another, webpack treats this as a _dependency_. This allows webpack to take non-code assets, such as images or web fonts, and also provide them as _dependencies_ for your application. - -When webpack processes your application, it starts from a list of modules defined on the command line or in its config file. -Starting from these [_entry points_](/concepts/entry-points/), webpack recursively builds a _dependency graph_ that includes every module your application needs, then bundles all of those modules into a small number of _bundles_ - often, just one - to be loaded by the browser. - -T> Bundling your application is especially powerful for _HTTP/1.1_ clients, as it minimizes the number of times your app has to wait while the browser starts a new request. For _HTTP/2_, you can also use [Code Splitting](/guides/code-splitting/) to achieve best results. - - -# Targets - -Because JavaScript can be written for both server and browser, webpack offers multiple deployment _targets_ that you can set in your webpack [configuration](/configuration). - -W> The webpack `target` property is not to be confused with the `output.libraryTarget` property. For more information see [our guide](/concepts/output/) on the `output` property. - -## Usage - -To set the `target` property, you simply set the target value in your webpack config: - -__webpack.config.js__ - -```javascript -module.exports = { - target: 'node' -}; -``` - -In the example above, using `node` webpack will compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks and not touch any built in modules like `fs` or `path`). - -Each _target_ has a variety of deployment/environment specific additions, support to fit its needs. See what [targets are available](/configuration/target/). - -?>Further expansion for other popular target values - -## Multiple Targets - -Although webpack does __not__ support multiple strings being passed into the `target` property, you can create an isomorphic library by bundling two separate configurations: - -__webpack.config.js__ - -```javascript -const path = require('path'); -const serverConfig = { - target: 'node', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'lib.node.js' - } - //… -}; - -const clientConfig = { - target: 'web', // <=== can be omitted as default is 'web' - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'lib.js' - } - //… -}; - -module.exports = [ serverConfig, clientConfig ]; -``` - -The example above will create a `lib.js` and `lib.node.js` file in your `dist` folder. - -## Resources - -As seen from the options above there are multiple different deployment _targets_ that you can choose from. Below is a list of examples, and resources that you can refer to. - -- __[compare-webpack-target-bundles](https://github.com/TheLarkInn/compare-webpack-target-bundles)__: A great resource for testing and viewing different webpack _targets_. Also great for bug reporting. -- __[Boilerplate of Electron-React Application](https://github.com/chentsulin/electron-react-boilerplate)__: A good example of a build process for electron's main process and renderer process. - -?> Need to find up to date examples of these webpack targets being used in live code or boilerplates. - - -# The Manifest - -In a typical application or site built with webpack, there are three main types of code: - -1. The source code you, and maybe your team, have written. -2. Any third-party library or "vendor" code your source is dependent on. -3. A webpack runtime and __manifest__ that conducts the interaction of all modules. - -This article will focus on the last of these three parts, the runtime and in particular the manifest. - - -## Runtime - -The runtime, along with the manifest data, is basically all the code webpack needs to connect your modularized application while it's running in the browser. It contains the loading and resolving logic needed to connect your modules as they interact. This includes connecting modules that have already been loaded into the browser as well as logic to lazy-load the ones that haven't. - - -## Manifest - -Once your application hits the browser in the form of `index.html` file, some bundles and a variety of other assets required by your application must be loaded and linked somehow. That `/src` directory you meticulously laid out is now bundled, minified and maybe even split into smaller chunks for lazy-loading by webpack's [`optimization`](/configuration/optimization/). So how does webpack manage the interaction between all of your required modules? This is where the manifest data comes in... - -As the compiler enters, resolves, and maps out your application, it keeps detailed notes on all your modules. This collection of data is called the "Manifest" and it's what the runtime will use to resolve and load modules once they've been bundled and shipped to the browser. No matter which [module syntax](/api/module-methods) you have chosen, those `import` or `require` statements have now become `__webpack_require__` methods that point to module identifiers. Using the data in the manifest, the runtime will be able to find out where to retrieve the modules behind the identifiers. - - -## The Problem - -So now you have a little bit of insight about how webpack works behind the scenes. "But, how does this affect me?", you might ask. The simple answer is that most of the time it doesn't. The runtime will do its thing, utilizing the manifest, and everything will appear to just magically work once your application hits the browser. However, if you decide to improve your projects performance by utilizing browser caching, this process will all of a sudden become an important thing to understand. - -By using content hashes within your bundle file names, you can indicate to the browser when the contents of a file has changed thus invalidating the cache. Once you start doing this though, you'll immediately notice some funny behavior. Certain hashes change even when their contents apparently do not. This is caused by the injection of the runtime and manifest which changes every build. - -See [the manifest section](/guides/output-management/#the-manifest) of our _Output management_ guide to learn how to extract the manifest, and read the guides below to learn more about the intricacies of long term caching. - - -# Hot Module Replacement - -Hot Module Replacement (HMR) exchanges, adds, or removes [modules](/concepts/modules/) while an application is running, without a full reload. This can significantly speed up development in a few ways: - -- Retain application state which is lost during a full reload. -- Save valuable development time by only updating what's changed. -- Modifications made to CSS/JS in the source code results in an instant browser update which is almost comparable to changing styles directly in the browser's dev tools. - - -## How It Works - -Let's go through some different viewpoints to understand exactly how HMR works... - -### In the Application - -The following steps allow modules to be swapped in and out of an application: - -1. The application asks the HMR runtime to check for updates. -2. The runtime asynchronously downloads the updates and notifies the application. -3. The application then asks the runtime to apply the updates. -4. The runtime synchronously applies the updates. - -You can set up HMR so that this process happens automatically, or you can choose to require user interaction for updates to occur. - - -### In the Compiler - -In addition to normal assets, the compiler needs to emit an "update" to allow updating from previous version to the new version. The "update" consists of two parts: - -1. The updated [manifest](/concepts/manifest) (JSON) -2. One or more updated chunks (JavaScript) - -The manifest contains the new compilation hash and a list of all updated chunks. Each of these chunks contains the new code for all updated modules (or a flag indicating that the module was removed). - -The compiler ensures that module IDs and chunk IDs are consistent between these builds. It typically stores these IDs in memory (e.g. with [webpack-dev-server](/configuration/dev-server/)), but it's also possible to store them in a JSON file. - - -### In a Module - -HMR is an opt-in feature that only affects modules containing HMR code. One example would be patching styling through the [`style-loader`](https://github.com/webpack-contrib/style-loader). In order for patching to work, the `style-loader` implements the HMR interface; when it receives an update through HMR, it replaces the old styles with the new ones. - -Similarly, when implementing the HMR interface in a module, you can describe what should happen when the module is updated. However, in most cases, it's not mandatory to write HMR code in every module. If a module has no HMR handlers, the update bubbles up. This means that a single handler can update a complete module tree. If a single module from the tree is updated, the entire set of dependencies is reloaded. - -See the [HMR API page](/api/hot-module-replacement) for details on the `module.hot` interface. - - -### In the Runtime - -Here things get a bit more technical... if you're not interested in the internals, feel free to jump to the [HMR API page](/api/hot-module-replacement) or [HMR guide](/guides/hot-module-replacement). - -For the module system runtime, additional code is emitted to track module `parents` and `children`. On the management side, the runtime supports two methods: `check` and `apply`. - -A `check` makes an HTTP request to the update manifest. If this request fails, there is no update available. If it succeeds, the list of updated chunks is compared to the list of currently loaded chunks. For each loaded chunk, the corresponding update chunk is downloaded. All module updates are stored in the runtime. When all update chunks have been downloaded and are ready to be applied, the runtime switches into the `ready` state. - -The `apply` method flags all updated modules as invalid. For each invalid module, there needs to be an update handler in the module or in its parent(s). Otherwise, the invalid flag bubbles up and invalidates parent(s) as well. Each bubble continues until the app's entry point or a module with an update handler is reached (whichever comes first). If it bubbles up from an entry point, the process fails. - -Afterwards, all invalid modules are disposed (via the dispose handler) and unloaded. The current hash is then updated and all `accept` handlers are called. The runtime switches back to the `idle` state and everything continues as normal. - - -## Get Started - -HMR can be used in development as a LiveReload replacement. [webpack-dev-server](/configuration/dev-server/) supports a `hot` mode in which it tries to update with HMR before trying to reload the whole page. See the [Hot Module Replacement guide](/guides/hot-module-replacement) for details. - -T> As with many other features, webpack's power lies in its customizability. There are _many_ ways of configuring HMR depending on the needs of a particular project. However, for most purposes, `webpack-dev-server` is a good fit and will allow you to get started with HMR quickly. diff --git a/src/content/configuration/_configuration_all.md b/src/content/configuration/_configuration_all.md deleted file mode 100644 index a1e52dc062a1..000000000000 --- a/src/content/configuration/_configuration_all.md +++ /dev/null @@ -1,5315 +0,0 @@ - - -# Configuration - -Out of the box, webpack won't require you to use a configuration file. However, it will assume the entry point of your project is `src/index` and will output the result in `dist/main.js` minified and optimized for production. - -Usually your projects will need to extend this functionality, for this you can create a `webpack.config.js` file in the root folder and webpack will automatically use it. - -All the available configuration options are specified below. - -T> New to webpack? Check out our guide to some of webpack's [core concepts](/concepts/) to get started! - -## Options - -Click on the name of each option in the configuration code below to jump to the detailed documentation. Also note that the items with arrows can be expanded to show more examples and, in some cases, more advanced configuration. - -W> Notice that throughout the configuration we use Node's built-in [path module](https://nodejs.org/api/path.html) and prefix it with the [__dirname](https://nodejs.org/docs/latest/api/globals.html#globals_dirname) global. This prevents file path issues between operating systems and allows relative paths to work as expected. See [this section](https://nodejs.org/api/path.html#path_windows_vs_posix) for more info on POSIX vs. Windows paths. - -__webpack.config.js__ - -```js-with-links-with-details -const path = require('path'); - -module.exports = { - <details><summary>[mode](/concepts/mode): "production", // "production" | "development" | "none"</summary> - [mode](/concepts/mode): "production", // enable many optimizations for production builds - [mode](/concepts/mode): "development", // enabled useful tools for development - [mode](/concepts/mode): "none", // no defaults - </details> - // Chosen mode tells webpack to use its built-in optimizations accordingly. - <details><summary>[entry](/configuration/entry-context#entry): "./app/entry", // string | object | array</summary> - [entry](/configuration/entry-context#entry): ["./app/entry1", "./app/entry2"], - [entry](/configuration/entry-context#entry): { - a: "./app/entry-a", - b: ["./app/entry-b1", "./app/entry-b2"] - }, - </details> - // defaults to './src' - // Here the application starts executing - // and webpack starts bundling - [output](/configuration/output): { - // options related to how webpack emits results - [path](/configuration/output#output-path): path.resolve(__dirname, "dist"), // string - // the target directory for all output files - // must be an absolute path (use the Node.js path module) - <details><summary>[filename](/configuration/output#output-filename): "bundle.js", // string</summary> - [filename](/configuration/output#output-filename): "[name].js", // for multiple entry points - [filename](/configuration/output#output-filename): "[chunkhash].js", // for [long term caching](/guides/caching) - </details> - // the filename template for entry chunks - <details><summary>[publicPath](/configuration/output#output-publicpath): "/assets/", // string</summary> - [publicPath](/configuration/output#output-publicpath): "", - [publicPath](/configuration/output#output-publicpath): "https://cdn.example.com/", - </details> - // the url to the output directory resolved relative to the HTML page - [library](/configuration/output#output-library): "MyLibrary", // string, - // the name of the exported library - <details><summary>[libraryTarget](/configuration/output#output-librarytarget): "umd", // universal module definition</summary> - [libraryTarget](/configuration/output#output-librarytarget): "umd2", // universal module definition - [libraryTarget](/configuration/output#output-librarytarget): "commonjs2", // exported with module.exports - [libraryTarget](/configuration/output#output-librarytarget): "commonjs", // exported as properties to exports - [libraryTarget](/configuration/output#output-librarytarget): "amd", // defined with AMD defined method - [libraryTarget](/configuration/output#output-librarytarget): "this", // property set on this - [libraryTarget](/configuration/output#output-librarytarget): "var", // variable defined in root scope - [libraryTarget](/configuration/output#output-librarytarget): "assign", // blind assignment - [libraryTarget](/configuration/output#output-librarytarget): "window", // property set to window object - [libraryTarget](/configuration/output#output-librarytarget): "global", // property set to global object - [libraryTarget](/configuration/output#output-librarytarget): "jsonp", // jsonp wrapper - </details> - // the type of the exported library - <details><summary>/* Advanced output configuration (click to show) */</summary> - [pathinfo](/configuration/output#output-pathinfo): true, // boolean - // include useful path info about modules, exports, requests, etc. into the generated cod - [chunkFilename](/configuration/output#output-chunkfilename): "[id].js", - [chunkFilename](/configuration/output#output-chunkfilename): "[chunkhash].js", // for [long term caching](/guides/caching) - // the filename template for additional chunks - [jsonpFunction](/configuration/output#output-jsonpfunction): "myWebpackJsonp", // string - // name of the JSONP function used to load chunks - [sourceMapFilename](/configuration/output#output-sourcemapfilename): "[file].map", // string - [sourceMapFilename](/configuration/output#output-sourcemapfilename): "sourcemaps/[file].map", // string - // the filename template of the source map location - [devtoolModuleFilenameTemplate](/configuration/output#output-devtoolmodulefilenametemplate): "webpack:///[resource-path]", // string - // the name template for modules in a devtool - [devtoolFallbackModuleFilenameTemplate](/configuration/output#output-devtoolfallbackmodulefilenametemplate): "webpack:///[resource-path]?[hash]", // string - // the name template for modules in a devtool (used for conflicts) - [umdNamedDefine](/configuration/output#output-umdnameddefine): true, // boolean - // use a named AMD module in UMD library - [crossOriginLoading](/configuration/output#output-crossoriginloading): "use-credentials", // enum - [crossOriginLoading](/configuration/output#output-crossoriginloading): "anonymous", - [crossOriginLoading](/configuration/output#output-crossoriginloading): false, - // specifies how cross origin request are issued by the runtime - <details><summary>/* Expert output configuration (on own risk) */</summary> - [devtoolLineToLine](/configuration/output#output-devtoollinetoline): { - test: /\.jsx$/ - }, - // use a simple 1:1 mapped SourceMaps for these modules (faster) - [hotUpdateMainFilename](/configuration/output#output-hotupdatemainfilename): "[hash].hot-update.json", // string - // filename template for HMR manifest - [hotUpdateChunkFilename](/configuration/output#output-hotupdatechunkfilename): "[id].[hash].hot-update.js", // string - // filename template for HMR chunks - [sourcePrefix](/configuration/output#output-sourceprefix): "\t", // string - // prefix module sources in bundle for better readablitity - </details> - </details> - }, - [module](/configuration/module): { - // configuration regarding modules - [rules](/configuration/module#module-rules): [ - // rules for modules (configure loaders, parser options, etc.) - { - [test](/configuration/module#rule-test): /\.jsx?$/, - [include](/configuration/module#rule-include): [ - path.resolve(__dirname, "app") - ], - [exclude](/configuration/module#rule-exclude): [ - path.resolve(__dirname, "app/demo-files") - ], - // these are matching conditions, each accepting a regular expression or string - // test and include have the same behavior, both must be matched - // exclude must not be matched (takes preference over test and include) - // Best practices: - // - Use RegExp only in test and for filename matching - // - Use arrays of absolute paths in include and exclude - // - Try to avoid exclude and prefer include - [issuer](/configuration/module#rule-issuer): { test, include, exclude }, - // conditions for the issuer (the origin of the import) - [enforce](/configuration/module#rule-enforce): "pre", - [enforce](/configuration/module#rule-enforce): "post", - // flags to apply these rules, even if they are overridden (advanced option) - [loader](/configuration/module#rule-loader): "babel-loader", - // the loader which should be applied, it'll be resolved relative to the context - // -loader suffix is no longer optional in webpack2 for clarity reasons - // see [webpack 1 upgrade guide](/migrate/3/#automatic-loader-module-name-extension-removed) - [options](/configuration/module#rule-options-rule-query): { - presets: ["es2015"] - }, - // options for the loader - }, - { - [test](/configuration/module#rule-test): /\.html$/, - [use](/configuration/module#rule-use): [ - // apply multiple loaders and options - "htmllint-loader", - { - loader: "html-loader", - options: { - /* ... */ - } - } - ] - }, - { [oneOf](/configuration/module#rule-oneof): [ /* rules */ ] }, - // only use one of these nested rules - { [rules](/configuration/module#rule-rules): [ /* rules */ ] }, - // use all of these nested rules (combine with conditions to be useful) - { [resource](/configuration/module#rule-resource): { [and](/configuration/module#condition): [ /* conditions */ ] } }, - // matches only if all conditions are matched - { [resource](/configuration/module#rule-resource): { [or](/configuration/module#condition): [ /* conditions */ ] } }, - { [resource](/configuration/module#rule-resource): [ /* conditions */ ] }, - // matches if any condition is matched (default for arrays) - { [resource](/configuration/module#rule-resource): { [not](/configuration/module#condition): /* condition */ } } - // matches if the condition is not matched - ], - <details><summary>/* Advanced module configuration (click to show) */</summary> - [noParse](/configuration/module#module-noparse): [ - /special-library\.js$/ - ], - // do not parse this module - unknownContextRequest: ".", - unknownContextRecursive: true, - unknownContextRegExp: /^\.\/.*$/, - unknownContextCritical: true, - exprContextRequest: ".", - exprContextRegExp: /^\.\/.*$/, - exprContextRecursive: true, - exprContextCritical: true, - wrappedContextRegExp: /.*/, - wrappedContextRecursive: true, - wrappedContextCritical: false, - // specifies default behavior for dynamic requests - </details> - }, - [resolve](/configuration/resolve): { - // options for resolving module requests - // (does not apply to resolving to loaders) - [modules](/configuration/resolve#resolve-modules): [ - "node_modules", - path.resolve(__dirname, "app") - ], - // directories where to look for modules - [extensions](/configuration/resolve#resolve-extensions): [".js", ".json", ".jsx", ".css"], - // extensions that are used - [alias](/configuration/resolve#resolve-alias): { - // a list of module name aliases - "module": "new-module", - // alias "module" -> "new-module" and "module/path/file" -> "new-module/path/file" - "only-module$": "new-module", - // alias "only-module" -> "new-module", but not "only-module/path/file" -> "new-module/path/file" - "module": path.resolve(__dirname, "app/third/module.js"), - // alias "module" -> "./app/third/module.js" and "module/file" results in error - // modules aliases are imported relative to the current context - }, - <details><summary>/* alternative alias syntax (click to show) */</summary> - [alias](/configuration/resolve#resolve-alias): [ - { - name: "module", - // the old request - alias: "new-module", - // the new request - onlyModule: true - // if true only "module" is aliased - // if false "module/inner/path" is also aliased - } - ], - </details> - <details><summary>/* Advanced resolve configuration (click to show) */</summary> - [symlinks](/configuration/resolve#resolve-symlinks): true, - // follow symlinks to new location - [descriptionFiles](/configuration/resolve#resolve-descriptionfiles): ["package.json"], - // files that are read for package description - [mainFields](/configuration/resolve#resolve-mainfields): ["main"], - // properties that are read from description file - // when a folder is requested - [aliasFields](/configuration/resolve#resolve-aliasfields): ["browser"], - // properties that are read from description file - // to alias requests in this package - [enforceExtension](/configuration/resolve#resolve-enforceextension): false, - // if true request must not include an extensions - // if false request may already include an extension - [moduleExtensions](/configuration/resolve#resolveloader-moduleextensions): ["-module"], - [enforceModuleExtension](/configuration/resolve#resolve-enforcemoduleextension): false, - // like extensions/enforceExtension but for module names instead of files - [unsafeCache](/configuration/resolve#resolve-unsafecache): true, - [unsafeCache](/configuration/resolve#resolve-unsafecache): {}, - // enables caching for resolved requests - // this is unsafe as folder structure may change - // but performance improvement is really big - [cachePredicate](/configuration/resolve#resolve-cachepredicate): (path, request) => true, - // predicate function which selects requests for caching - [plugins](/configuration/resolve#resolve-plugins): [ - // ... - ] - // additional plugins applied to the resolver - </details> - }, - [performance](/configuration/performance): { - <details><summary>[hints](/configuration/performance#performance-hints): "warning", // enum </summary> - [hints](/configuration/performance#performance-hints): "error", // emit errors for perf hints - [hints](/configuration/performance#performance-hints): false, // turn off perf hints - </details> - [maxAssetSize](/configuration/performance#performance-maxassetsize): 200000, // int (in bytes), - [maxEntrypointSize](/configuration/performance#performance-maxentrypointsize): 400000, // int (in bytes) - [assetFilter](/configuration/performance#performance-assetfilter): function(assetFilename) { - // Function predicate that provides asset filenames - return assetFilename.endsWith('.css') || assetFilename.endsWith('.js'); - } - }, - <details><summary>[devtool](/configuration/devtool): "source-map", // enum </summary> - [devtool](/configuration/devtool): "inline-source-map", // inlines SourceMap into original file - [devtool](/configuration/devtool): "eval-source-map", // inlines SourceMap per module - [devtool](/configuration/devtool): "hidden-source-map", // SourceMap without reference in original file - [devtool](/configuration/devtool): "cheap-source-map", // cheap-variant of SourceMap without module mappings - [devtool](/configuration/devtool): "cheap-module-source-map", // cheap-variant of SourceMap with module mappings - [devtool](/configuration/devtool): "eval", // no SourceMap, but named modules. Fastest at the expense of detail. - </details> - // enhance debugging by adding meta info for the browser devtools - // source-map most detailed at the expense of build speed. - [context](/configuration/entry-context#context): __dirname, // string (absolute path!) - // the home directory for webpack - // the [entry](/configuration/entry-context) and [module.rules.loader](/configuration/module#rule-loader) option - // is resolved relative to this directory - <details><summary>[target](/configuration/target): "web", // enum</summary> - [target](/configuration/target): "webworker", // WebWorker - [target](/configuration/target): "node", // Node.js via require - [target](/configuration/target): "async-node", // Node.js via fs and vm - [target](/configuration/target): "node-webkit", // nw.js - [target](/configuration/target): "electron-main", // electron, main process - [target](/configuration/target): "electron-renderer", // electron, renderer process - [target](/configuration/target): (compiler) => { /* ... */ }, // custom - </details> - // the environment in which the bundle should run - // changes chunk loading behavior and available modules - <details><summary>[externals](/configuration/externals): ["react", /^@angular\//],</summary> - [externals](/configuration/externals): "react", // string (exact match) - [externals](/configuration/externals): /^[a-z\-]+($|\/)/, // Regex - [externals](/configuration/externals): { // object - angular: "this angular", // this["angular"] - react: { // UMD - commonjs: "react", - commonjs2: "react", - amd: "react", - root: "React" - } - }, - [externals](/configuration/externals): (request) => { /* ... */ return "commonjs " + request } - </details> - // Don't follow/bundle these modules, but request them at runtime from the environment - [serve](https://github.com/webpack-contrib/webpack-serve#options): { //object - port: 1337, - content: './dist', - // ... - }, - // lets you provide options for webpack-serve - <details><summary>[stats](/configuration/stats): "errors-only",</summary> - [stats](/configuration/stats): { //object - assets: true, - colors: true, - errors: true, - errorDetails: true, - hash: true, - // ... - }, - </details> - // lets you precisely control what bundle information gets displayed - [devServer](/configuration/dev-server): { - proxy: { // proxy URLs to backend development server - '/api': 'http://localhost:3000' - }, - contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location - compress: true, // enable gzip compression - historyApiFallback: true, // true for index.html upon 404, object for multiple paths - hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin - https: false, // true for self-signed, object for cert authority - noInfo: true, // only errors & warns on hot reload - // ... - }, - [plugins](plugins): [ - // ... - ], - // list of additional plugins - <details><summary>/* Advanced configuration (click to show) */</summary> - [resolveLoader](/configuration/resolve#resolveloader): { /* same as resolve */ } - // separate resolve options for loaders - [parallelism](other-options#parallelism): 1, // number - // limit the number of parallel processed modules - [profile](other-options#profile): true, // boolean - // capture timing information - [bail](other-options#bail): true, //boolean - // fail out on the first error instead of tolerating it. - [cache](other-options#cache): false, // boolean - // disable/enable caching - [watch](watch#watch): true, // boolean - // enables watching - [watchOptions](watch#watchoptions): { - [aggregateTimeout](watch#watchoptions-aggregatetimeout): 1000, // in ms - // aggregates multiple changes to a single rebuild - [poll](watch#watchoptions-poll): true, - [poll](watch#watchoptions-poll): 500, // interval in ms - // enables polling mode for watching - // must be used on filesystems that doesn't notify on change - // i. e. nfs shares - }, - [node](node): { - // Polyfills and mocks to run Node.js- - // environment code in non-Node environments. - [console](node#node-console): false, // boolean | "mock" - [global](node#node-global): true, // boolean | "mock" - [process](node#node-process): true, // boolean - [__filename](node#node-__filename): "mock", // boolean | "mock" - [__dirname](node#node-__dirname): "mock", // boolean | "mock" - [Buffer](node#node-buffer): true, // boolean | "mock" - [setImmediate](node#node-setimmediate): true // boolean | "mock" | "empty" - }, - [recordsPath](other-options#recordspath): path.resolve(__dirname, "build/records.json"), - [recordsInputPath](other-options#recordsinputpath): path.resolve(__dirname, "build/records.json"), - [recordsOutputPath](other-options#recordsoutputpath): path.resolve(__dirname, "build/records.json"), - // TODO - </details> -} -``` - -## Use custom configuration file - -If for some reason you want to use custom configuration file depending on certain situations you can change this via command line by using the `--config` flag. - -__package.json__ - -```json -"scripts": { - "build": "webpack --config prod.config.js" -} -``` - -## Configuration file generators - -Want to rapidly generate webpack configuration file for your project requirements with few clicks away? - -[Generate Custom Webpack Configuration](https://generatewebpackconfig.netlify.com/) is an interactive portal you can play around by selecting custom webpack configuration options tailored for your frontend project. It automatically generates a minimal webpack configuration based on your selection of loaders/plugins, etc. - -[Visual tool for creating webpack configs](https://webpack.jakoblind.no/) is an online configuration tool for creating webpack configuration file where you can select any combination of features you need. It also generates a full example project based on your webpack configs. - - -# Configuration Languages - -webpack accepts configuration files written in multiple programming and data languages. The list of supported file extensions can be found at the [node-interpret](https://github.com/js-cli/js-interpret) package. Using [node-interpret](https://github.com/js-cli/js-interpret), webpack can handle many different types of configuration files. - - -## TypeScript - -To write the webpack configuration in [TypeScript](http://www.typescriptlang.org/), you would first install the necessary dependencies, i.e., TypeScript and the relevant type definitions from the [DefinitelyTyped](https://definitelytyped.org/) project: - -``` bash -npm install --save-dev typescript ts-node @types/node @types/webpack -# and, if using webpack-dev-server -npm install --save-dev @types/webpack-dev-server -``` - -and then proceed to write your configuration: - -__webpack.config.ts__ - -```typescript -import path from 'path'; -import webpack from 'webpack'; - -const config: webpack.Configuration = { - mode: 'production', - entry: './foo.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'foo.bundle.js' - } -}; - -export default config; -``` - -Above sample assumes version >= 2.7 or newer of TypeScript is used with the new `esModuleInterop` and `allowSyntheticDefaultImports` compiler options in your `tsconfig.json` file. - -Note that you'll also need to check your `tsconfig.json` file. If the module in `compilerOptions` in `tsconfig.json` is `commonjs`, the setting is complete, else webpack will fail with an error. This occurs because `ts-node` does not support any module syntax other than `commonjs`. - -There are two solutions to this issue: - -- Modify `tsconfig.json`. -- Install `tsconfig-paths`. - -The __first option__ is to open your `tsconfig.json` file and look for `compilerOptions`. Set `target` to `"ES5"` and `module` to `"CommonJS"` (or completely remove the `module` option). - -The __second option__ is to install the `tsconfig-paths` package: - -``` bash -npm install --save-dev tsconfig-paths -``` - -And create a separate TypeScript configuration specifically for your webpack configs: - -__tsconfig-for-webpack-config.json__ - -``` json -{ - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "esModuleInterop": true - } -} -``` - -T> `ts-node` can resolve a `tsconfig.json` file using the environment variable provided by `tsconfig-path`. - -Then set the environment variable `process.env.TS_NODE_PROJECT` provided by `tsconfig-path` like so: - -__package.json__ - -```json -{ - "scripts": { - "build": "TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack" - } -} -``` - - -## CoffeeScript - -Similarly, to use [CoffeeScript](http://coffeescript.org/), you would first install the necessary dependencies: - -``` bash -npm install --save-dev coffee-script -``` - -and then proceed to write your configuration: - -__webpack.config.coffee__ - -<!-- eslint-skip --> - -```js -HtmlWebpackPlugin = require('html-webpack-plugin') -webpack = require('webpack') -path = require('path') - -config = - mode: 'production' - entry: './path/to/my/entry/file.js' - output: - path: path.resolve(__dirname, 'dist') - filename: 'my-first-webpack.bundle.js' - module: rules: [ { - test: /\.(js|jsx)$/ - use: 'babel-loader' - } ] - plugins: [ - new HtmlWebpackPlugin(template: './src/index.html') - ] - -module.exports = config -``` - - -## Babel and JSX - -In the example below JSX (React JavaScript Markup) and Babel are used to create a JSON Configuration that webpack can understand. - -> Courtesy of [Jason Miller](https://twitter.com/_developit/status/769583291666169862) - -First install the necessary dependencies: - -``` bash -npm install --save-dev babel-register jsxobj babel-preset-es2015 -``` - -__.babelrc__ - -``` json -{ - "presets": [ "es2015" ] -} -``` - -__webpack.config.babel.js__ - -``` js -import jsxobj from 'jsxobj'; - -// example of an imported plugin -const CustomPlugin = config => ({ - ...config, - name: 'custom-plugin' -}); - -export default ( - <webpack target="web" watch mode="production"> - <entry path="src/index.js" /> - <resolve> - <alias {...{ - react: 'preact-compat', - 'react-dom': 'preact-compat' - }} /> - </resolve> - <plugins> - <CustomPlugin foo="bar" /> - </plugins> - </webpack> -); -``` - -W> If you are using Babel elsewhere and have `modules` set to `false`, you will have to either maintain two separate `.babelrc` files or use `const jsxobj = require('jsxobj');` and `module.exports` instead of the new `import` and `export` syntax. This is because while Node does support many new ES6 features, they don't yet support ES6 module syntax. - - -# Configuration Types - -Besides exporting a single config object, there are a few more ways that cover other needs as well. - - -## Exporting a Function - -Eventually you will find the need to disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production). You have (at least) two options: - -One option is to export a function from your webpack config instead of exporting an object. The function will be invoked with two arguments: - -- An environment as the first parameter. See the [environment options CLI documentation](/api/cli#environment-options) for syntax examples. -- An options map (`argv`) as the second parameter. This describes the options passed to webpack, with keys such as [`output-filename`](/api/cli/#output-options) and [`optimize-minimize`](/api/cli/#optimize-options). - -```diff --module.exports = { -+module.exports = function(env, argv) { -+ return { -+ mode: env.production ? 'production' : 'development', -+ devtool: env.production ? 'source-maps' : 'eval', - plugins: [ - new TerserPlugin({ - terserOptions: { -+ compress: argv['optimize-minimize'] // only if -p or --optimize-minimize were passed - } - }) - ] -+ }; -}; -``` - - -## Exporting a Promise - -webpack will run the function exported by the configuration file and wait for a Promise to be returned. Handy when you need to asynchronously load configuration variables. - -```js -module.exports = () => { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve({ - entry: './app.js', - /* ... */ - }); - }, 5000); - }); -}; -``` - - -## Exporting multiple configurations - -Instead of exporting a single configuration object/function, you may export multiple configurations (multiple functions are supported since webpack 3.1.0). When running webpack, all configurations are built. For instance, this is useful for [bundling a library](/guides/author-libraries) for multiple [targets](/configuration/output#output-librarytarget) such as AMD and CommonJS: - -```js -module.exports = [{ - output: { - filename: './dist-amd.js', - libraryTarget: 'amd' - }, - name: 'amd', - entry: './app.js', - mode: 'production', -}, { - output: { - filename: './dist-commonjs.js', - libraryTarget: 'commonjs' - }, - name: 'commonjs', - entry: './app.js', - mode: 'production', -}]; -``` - -T> If you pass a name to [`--config-name`](/api/cli/#config-options) flag, webpack will only build that specific configuration. - - -# Entry and Context - -The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. - - -## `context` - -`string` - -The base directory, an __absolute path__, for resolving entry points and loaders from configuration. - -``` js -module.exports = { - //... - context: path.resolve(__dirname, 'app') -}; -``` - -By default the current directory is used, but it's recommended to pass a value in your configuration. This makes your configuration independent from CWD (current working directory). - ---- - - -## `entry` - -`string | [string] | object { <key>: string | [string] } | (function: () => string | [string] | object { <key>: string | [string] })` - -The point or points to enter the application. At this point the application starts executing. If an array is passed all items will be executed. - -A dynamically loaded module is __not__ an entry point. - -Simple rule: one entry point per HTML page. SPA: one entry point, MPA: multiple entry points. - -```js -module.exports = { - //... - entry: { - home: './home.js', - about: './about.js', - contact: './contact.js' - } -}; -``` - - -### Naming - -If a string or array of strings is passed, the chunk is named `main`. If an object is passed, each key is the name of a chunk, and the value describes the entry point for the chunk. - - -### Dynamic entry - -If a function is passed then it will be invoked on every [make](/api/compiler-hooks/#make) event. - -> Note that the make event triggers when webpack starts and for every invalidation when [watching for file changes](/configuration/watch/). - -```js -module.exports = { - //... - entry: () => './demo' -}; -``` - -or - -```js -module.exports = { - //... - entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])) -}; -``` - -For example: you can use dynamic entries to get the actual entries from an external source (remote server, file system content or database): - -__webpack.config.js__ - -``` js -module.exports = { - entry() { - return fetchPathsFromSomeExternalSource(); // returns a promise that will be resolved with something like ['src/main-layout.js', 'src/admin-layout.js'] - } -}; -``` - -When combining with the [`output.library`](/configuration/output#output-library) option: If an array is passed only the last item is exported. - - -# Output - -The top-level `output` key contains set of options instructing webpack on how and where it should output your bundles, assets and anything else you bundle or load with webpack. - - -## `output.auxiliaryComment` - -`string` `object` - -When used in tandem with [`output.library`](#output-library) and [`output.libraryTarget`](#output-librarytarget), this option allows users to insert comments within the export wrapper. To insert the same comment for each `libraryTarget` type, set `auxiliaryComment` to a string: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - library: 'someLibName', - libraryTarget: 'umd', - filename: 'someLibName.js', - auxiliaryComment: 'Test Comment' - } -}; -``` - -which will yield the following: - -__webpack.config.js__ - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - // Test Comment - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require('lodash')); - // Test Comment - else if(typeof define === 'function' && define.amd) - define(['lodash'], factory); - // Test Comment - else if(typeof exports === 'object') - exports['someLibName'] = factory(require('lodash')); - // Test Comment - else - root['someLibName'] = factory(root['_']); -})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { - // ... -}); -``` - -For fine-grained control over each `libraryTarget` comment, pass an object: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - //... - auxiliaryComment: { - root: 'Root Comment', - commonjs: 'CommonJS Comment', - commonjs2: 'CommonJS2 Comment', - amd: 'AMD Comment' - } - } -}; -``` - - -## `output.chunkFilename` - -`string` - -This option determines the name of non-entry chunk files. See [`output.filename`](#output-filename) option for details on the possible values. - -Note that these filenames need to be generated at runtime to send the requests for chunks. Because of this, placeholders like `[name]` and `[chunkhash]` need to add a mapping from chunk id to placeholder value to the output bundle with the webpack runtime. This increases the size and may invalidate the bundle when placeholder value for any chunk changes. - -By default `[id].js` is used or a value inferred from [`output.filename`](#output-filename) (`[name]` is replaced with `[id]` or `[id].` is prepended). - - -## `output.chunkLoadTimeout` - -`integer` - -Number of milliseconds before chunk request expires, defaults to 120 000. This option is supported since webpack 2.6.0. - - -## `output.crossOriginLoading` - -`boolean` `string` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks, by adding script tags. - -Enable [cross-origin](https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-crossorigin) loading of chunks. The following values are accepted... - -`crossOriginLoading: false` - Disable cross-origin loading (default) - -`crossOriginLoading: 'anonymous'` - Enable cross-origin loading __without credentials__ - -`crossOriginLoading: 'use-credentials'` - Enable cross-origin loading __with credentials__ - - -## `output.jsonpScriptType` - -`string` - -Allows customization of the `script` type webpack injects `script` tags into the DOM to download async chunks. The following options are available: - -- `'text/javascript'` (default) -- `'module'`: Use with ES6 ready code. - - -## `output.devtoolFallbackModuleFilenameTemplate` - -`string | function(info)` - -A fallback used when the template string or function above yields duplicates. - -See [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). - - -## `output.devtoolLineToLine` - -`boolean | object` - -> Avoid using this option as it is __deprecated__ and will soon be removed. - -Enables line to line mapping for all or some modules. This produces a simple source map where each line of the generated source is mapped to the same line of the original source. This is a performance optimization and should only be used if all input lines match generated lines. - -Pass a boolean to enable or disable this feature for all modules (defaults to `false`). An object with `test`, `include`, `exclude` is also allowed. For example, to enable this feature for all javascript files within a certain directory: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - devtoolLineToLine: { test: /\.js$/, include: 'src/utilities' } - } -}; -``` - - -## `output.devtoolModuleFilenameTemplate` - -`string | function(info)` - -This option is only used when [`devtool`](/configuration/devtool) uses an options which requires module names. - -Customize the names used in each source map's `sources` array. This can be done by passing a template string or function. For example, when using `devtool: 'eval'`, this is the default: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - devtoolModuleFilenameTemplate: 'webpack://[namespace]/[resource-path]?[loaders]' - } -}; -``` - -The following substitutions are available in template strings (via webpack's internal [`ModuleFilenameHelpers`](https://github.com/webpack/webpack/blob/master/lib/ModuleFilenameHelpers.js)): - -| Template | Description | -| ------------------------ | ----------- | -| [absolute-resource-path] | The absolute filename | -| [all-loaders] | Automatic and explicit loaders and params up to the name of the first loader | -| [hash] | The hash of the module identifier | -| [id] | The module identifier | -| [loaders] | Explicit loaders and params up to the name of the first loader | -| [resource] | The path used to resolve the file and any query params used on the first loader | -| [resource-path] | The path used to resolve the file without any query params | -| [namespace] | The modules namespace. This is usually the library name when building as a library, empty otherwise | - -When using a function, the same options are available camel-cased via the `info` parameter: - -```javascript -module.exports = { - //... - output: { - devtoolModuleFilenameTemplate: info => { - return `webpack:///${info.resourcePath}?${info.loaders}`; - } - } -}; -``` - -If multiple modules would result in the same name, [`output.devtoolFallbackModuleFilenameTemplate`](#output-devtoolfallbackmodulefilenametemplate) is used instead for these modules. - - -## `output.devtoolNamespace` - -`string` - -This option determines the modules namespace used with the [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). When not specified, it will default to the value of: [`output.library`](#output-library). It's used to prevent source file path collisions in source maps when loading multiple libraries built with webpack. - -For example, if you have 2 libraries, with namespaces `library1` and `library2`, which both have a file `./src/index.js` (with potentially different contents), they will expose these files as `webpack://library1/./src/index.js` and `webpack://library2/./src/index.js`. - - -## `output.filename` - -`string` `function` - -This option determines the name of each output bundle. The bundle is written to the directory specified by the [`output.path`](#output-path) option. - -For a single [`entry`](/configuration/entry-context#entry) point, this can be a static name. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: 'bundle.js' - } -}; -``` - -However, when creating multiple bundles via more than one entry point, code splitting, or various plugins, you should use one of the following substitutions to give each bundle a unique name... - -Using entry name: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[name].bundle.js' - } -}; -``` - -Using internal chunk id: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[id].bundle.js' - } -}; -``` - -Using the unique hash generated for every build: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[name].[hash].bundle.js' - } -}; -``` - -Using hashes based on each chunks' content: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[chunkhash].bundle.js' - } -}; -``` - -Using hashes generated for extracted content: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[contenthash].bundle.css' - } -}; -``` - -Using function to return the filename: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: (chunkData) => { - return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js'; - }, - } -}; -``` - -Make sure to read the [Caching guide](/guides/caching) for details. There are more steps involved than just setting this option. - -Note this option is called filename but you are still allowed to use something like `'js/[name]/bundle.js'` to create a folder structure. - -Note this option does not affect output files for on-demand-loaded chunks. For these files the [`output.chunkFilename`](#output-chunkfilename) option is used. Files created by loaders also aren't affected. In this case you would have to try the specific loader's available options. - -The following substitutions are available in template strings (via webpack's internal [`TemplatedPathPlugin`](https://github.com/webpack/webpack/blob/master/lib/TemplatedPathPlugin.js)): - -| Template | Description | -| ----------- | ----------------------------------------------------------------------------------- | -| [hash] | The hash of the module identifier | -| [chunkhash] | The hash of the chunk content | -| [name] | The module name | -| [id] | The module identifier | -| [query] | The module query, i.e., the string following `?` in the filename | -| [function] | The function, which can return filename [string] | - -The lengths of `[hash]` and `[chunkhash]` can be specified using `[hash:16]` (defaults to 20). Alternatively, specify [`output.hashDigestLength`](#output-hashdigestlength) to configure the length globally. - -If using a function for this option, the function will be passed an object containing the substitutions in the table above. - -T> When using the [`ExtractTextWebpackPlugin`](/plugins/extract-text-webpack-plugin), use `[contenthash]` to obtain a hash of the extracted file (neither `[hash]` nor `[chunkhash]` work). - - -## `output.hashDigest` - -The encoding to use when generating the hash, defaults to `'hex'`. All encodings from Node.JS' [`hash.digest`](https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding) are supported. Using `'base64'` for filenames might be problematic since it has the character `/` in its alphabet. Likewise `'latin1'` could contain any character. - - -## `output.hashDigestLength` - -The prefix length of the hash digest to use, defaults to `20`. - - -## `output.hashFunction` - -`string|function` - -The hashing algorithm to use, defaults to `'md4'`. All functions from Node.JS' [`crypto.createHash`](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options) are supported. Since `4.0.0-alpha2`, the `hashFunction` can now be a constructor to a custom hash function. You can provide a non-crypto hash function for performance reasons. - -```javascript -module.exports = { - //... - output: { - hashFunction: require('metrohash').MetroHash64 - } -}; -``` - -Make sure that the hashing function will have `update` and `digest` methods available. - -## `output.hashSalt` - -An optional salt to update the hash via Node.JS' [`hash.update`](https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding). - - -## `output.hotUpdateChunkFilename` - -`string` `function` - -Customize the filenames of hot update chunks. See [`output.filename`](#output-filename) option for details on the possible values. - -The only placeholders allowed here are `[id]` and `[hash]`, the default being: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - hotUpdateChunkFilename: '[id].[hash].hot-update.js' - } -}; -``` - -Here is no need to change it. - - -## `output.hotUpdateFunction` - -`function` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading hot updates. - -A JSONP function used to asynchronously load hot-update chunks. - -For details see [`output.jsonpFunction`](#output-jsonpfunction). - - -## `output.hotUpdateMainFilename` - -`string` `function` - -Customize the main hot update filename. See [`output.filename`](#output-filename) option for details on the possible values. - -`[hash]` is the only available placeholder, the default being: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - hotUpdateMainFilename: '[hash].hot-update.json' - } -}; -``` - -Here is no need to change it. - - -## `output.jsonpFunction` - -`string` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks. - -A JSONP function name used to asynchronously load chunks or join multiple initial chunks (SplitChunksPlugin, AggressiveSplittingPlugin). - -This needs to be changed if multiple webpack runtimes (from different compilation) are used on the same webpage. - -If using the [`output.library`](#output-library) option, the library name is automatically appended. - - -## `output.library` - -`string` or `object` (since webpack 3.1.0; for `libraryTarget: 'umd'`) - -How the value of the `output.library` is used depends on the value of the [`output.libraryTarget`](#output-librarytarget) option; please refer to that section for the complete details. Note that the default option for `output.libraryTarget` is `var`, so if the following configuration option is used: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary' - } -}; -``` - -The variable `MyLibrary` will be bound with the return value of your entry file, if the resulting output is included as a script tag in an HTML page. - -W> Note that if an `array` is provided as an `entry` point, only the last module in the array will be exposed. If an `object` is provided, it can be exposed using an `array` syntax (see [this example](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) for details). - -T> Read the [authoring libraries guide](/guides/author-libraries) guide for more information on `output.library` as well as `output.libraryTarget`. - - -## `output.libraryExport` - -`string | string[]` - -Configure which module or modules will be exposed via the `libraryTarget`. It is `undefined` by default, same behaviour will be applied if you set `libraryTarget` to an empty string e.g. `''` it will export the whole (namespace) object. The examples below demonstrate the effect of this config when using `libraryTarget: 'var'`. - -The following configurations are supported: - -`libraryExport: 'default'` - The __default export of your entry point__ will be assigned to the library target: - -```javascript -// if your entry has a default export of `MyDefaultModule` -var MyDefaultModule = _entry_return_.default; -``` - -`libraryExport: 'MyModule'` - The __specified module__ will be assigned to the library target: - -```javascript -var MyModule = _entry_return_.MyModule; -``` - -`libraryExport: ['MyModule', 'MySubModule']` - The array is interpreted as a __path to a module__ to be assigned to the library target: - -```javascript -var MySubModule = _entry_return_.MyModule.MySubModule; -``` - -With the `libraryExport` configurations specified above, the resulting libraries could be utilized as such: - -```javascript -MyDefaultModule.doSomething(); -MyModule.doSomething(); -MySubModule.doSomething(); -``` - - -## `output.libraryTarget` - -`string: 'var'` - -Configure how the library will be exposed. Any one of the following options can be used. Please note that this option works in conjunction with the value assigned to [`output.library`](#output-library). For the following examples, it is assumed that this value is configured as `MyLibrary`. - -T> Note that `_entry_return_` in the example code below is the value returned by the entry point. In the bundle itself, it is the output of the function that is generated by webpack from the entry point. - -### Expose a Variable - -These options assign the return value of the entry point (e.g. whatever the entry point exported) to the name provided by `output.library` at whatever scope the bundle was included at. - -`libraryTarget: 'var'` - (default) When your library is loaded, the __return value of your entry point__ will be assigned to a variable: - -```javascript -var MyLibrary = _entry_return_; - -// In a separate script... -MyLibrary.doSomething(); -``` - -W> When using this option, an empty `output.library` will result in no assignment. - - -`libraryTarget: 'assign'` - This will generate an implied global which has the potential to reassign an existing value (use with caution). - -```javascript -MyLibrary = _entry_return_; -``` - -Be aware that if `MyLibrary` isn't defined earlier your library will be set in global scope. - -W> When using this option, an empty `output.library` will result in a broken output bundle. - - -### Expose Via Object Assignment - -These options assign the return value of the entry point (e.g. whatever the entry point exported) to a specific object under the name defined by `output.library`. - -If `output.library` is not assigned a non-empty string, the default behavior is that all properties returned by the entry point will be assigned to the object as defined for the particular `output.libraryTarget`, via the following code fragment: - -```javascript -(function(e, a) { for(var i in a) { e[i] = a[i]; } }(output.libraryTarget, _entry_return_)); -``` - -W> Note that not setting a `output.library` will cause all properties returned by the entry point to be assigned to the given object; there are no checks against existing property names. - -`libraryTarget: "this"` - The __return value of your entry point__ will be assigned to this under the property named by `output.library`. The meaning of `this` is up to you: - -```javascript -this['MyLibrary'] = _entry_return_; - -// In a separate script... -this.MyLibrary.doSomething(); -MyLibrary.doSomething(); // if this is window -``` - -`libraryTarget: 'window'` - The __return value of your entry point__ will be assigned to the `window` object using the `output.library` value. - -```javascript -window['MyLibrary'] = _entry_return_; - -window.MyLibrary.doSomething(); -``` - - -`libraryTarget: 'global'` - The __return value of your entry point__ will be assigned to the `global` object using the `output.library` value. - -```javascript -global['MyLibrary'] = _entry_return_; - -global.MyLibrary.doSomething(); -``` - - -`libraryTarget: 'commonjs'` - The __return value of your entry point__ will be assigned to the `exports` object using the `output.library` value. As the name implies, this is used in CommonJS environments. - -```javascript -exports['MyLibrary'] = _entry_return_; - -require('MyLibrary').doSomething(); -``` - -### Module Definition Systems - -These options will result in a bundle that comes with a more complete header to ensure compatibility with various module systems. The `output.library` option will take on a different meaning under the following `output.libraryTarget` options. - - -`libraryTarget: 'commonjs2'` - The __return value of your entry point__ will be assigned to the `module.exports`. As the name implies, this is used in CommonJS environments: - -```javascript -module.exports = _entry_return_; - -require('MyLibrary').doSomething(); -``` - -Note that `output.library` is omitted, thus it is not required for this particular `output.libraryTarget`. - -T> Wondering the difference between CommonJS and CommonJS2 is? While they are similar, there are some subtle differences between them that are not usually relevant in the context of webpack. (For further details, please [read this issue](https://github.com/webpack/webpack/issues/1114).) - - -`libraryTarget: 'amd'` - This will expose your library as an AMD module. - -AMD modules require that the entry chunk (e.g. the first script loaded by the `<script>` tag) be defined with specific properties, such as `define` and `require` which is typically provided by RequireJS or any compatible loaders (such as almond). Otherwise, loading the resulting AMD bundle directly will result in an error like `define is not defined`. - -So, with the following configuration... - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary', - libraryTarget: 'amd' - } -}; -``` - -The generated output will be defined with the name "MyLibrary", i.e. - -```javascript -define('MyLibrary', [], function() { - return _entry_return_; -}); -``` - -The bundle can be included as part of a script tag, and the bundle can be invoked like so: - -```javascript -require(['MyLibrary'], function(MyLibrary) { - // Do something with the library... -}); -``` - -If `output.library` is undefined, the following is generated instead. - -```javascript -define([], function() { - return _entry_return_; -}); -``` - -This bundle will not work as expected, or not work at all (in the case of the almond loader) if loaded directly with a `<script>` tag. It will only work through a RequireJS compatible asynchronous module loader through the actual path to that file, so in this case, the `output.path` and `output.filename` may become important for this particular setup if these are exposed directly on the server. - - -`libraryTarget: 'amd-require'` - This packages your output with an immediately-executed AMD `require(dependencies, factory)` wrapper. - -The `'amd-require'` target allows for the use of AMD dependencies without needing a separate later invocation. As with the `'amd'` target, this depends on the appropriate [`require` function](https://github.com/amdjs/amdjs-api/blob/master/require.md) being available in the environment in which the webpack output is loaded. - -With this target, the library name is ignored. - - -`libraryTarget: 'umd'` - This exposes your library under all the module definitions, allowing it to work with CommonJS, AMD and as global variable. Take a look at the [UMD Repository](https://github.com/umdjs/umd) to learn more. - -In this case, you need the `library` property to name your module: - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary', - libraryTarget: 'umd' - } -}; -``` - -And finally the output is: - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports['MyLibrary'] = factory(); - else - root['MyLibrary'] = factory(); -})(typeof self !== 'undefined' ? self : this, function() { - return _entry_return_; -}); -``` - -Note that omitting `library` will result in the assignment of all properties returned by the entry point be assigned directly to the root object, as documented under the [object assignment section](#expose-via-object-assignment). Example: - -```javascript -module.exports = { - //... - output: { - libraryTarget: 'umd' - } -}; -``` - -The output will be: - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else { - var a = factory(); - for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; - } -})(typeof self !== 'undefined' ? self : this, function() { - return _entry_return_; -}); -``` - -Since webpack 3.1.0, you may specify an object for `library` for differing names per targets: - -```javascript -module.exports = { - //... - output: { - library: { - root: 'MyLibrary', - amd: 'my-library', - commonjs: 'my-common-library' - }, - libraryTarget: 'umd' - } -}; -``` - -Module proof library. - - -### Other Targets - -`libraryTarget: 'jsonp'` - This will wrap the return value of your entry point into a jsonp wrapper. - -``` javascript -MyLibrary(_entry_return_); -``` - -The dependencies for your library will be defined by the [`externals`](/configuration/externals/) config. - - -## `output.path` - -`string` - -The output directory as an __absolute__ path. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - path: path.resolve(__dirname, 'dist/assets') - } -}; -``` - -Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. - - -## `output.pathinfo` - -`boolean` - -Tells webpack to include comments in bundles with information about the contained modules. This option defaults to `true` in `development` and `false` in `production` [mode](/concepts/mode/) respectively. - -W> While the data this comments can provide is very useful during development when reading the generated code, it __should not__ be used in production. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - pathinfo: true - } -}; -``` - -Note it also adds some info about tree shaking to the generated bundle. - - -## `output.publicPath` - -`string: ''` `function` - -This is an important option when using on-demand-loading or loading external resources like images, files, etc. If an incorrect value is specified you'll receive 404 errors while loading these resources. - -This option specifies the __public URL__ of the output directory when referenced in a browser. A relative URL is resolved relative to the HTML page (or `<base>` tag). Server-relative URLs, protocol-relative URLs or absolute URLs are also possible and sometimes required, i. e. when hosting assets on a CDN. - -The value of the option is prefixed to every URL created by the runtime or loaders. Because of this __the value of this option ends with `/`__ in most cases. - -Simple rule: The URL of your [`output.path`](#output-path) from the view of the HTML page. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - path: path.resolve(__dirname, 'public/assets'), - publicPath: 'https://cdn.example.com/assets/' - } -}; -``` - -For this configuration: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - publicPath: '/assets/', - chunkFilename: '[id].chunk.js' - } -}; -``` - -A request to a chunk will look like `/assets/4.chunk.js`. - -A loader outputting HTML might emit something like this: - -```html -<link href="/assets/spinner.gif" /> -``` - -or when loading an image in CSS: - -```css -background-image: url(/assets/spinner.gif); -``` - -The webpack-dev-server also takes a hint from `publicPath`, using it to determine where to serve the output files from. - -Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. - -Examples: - -```javascript -module.exports = { - //... - output: { - // One of the below - publicPath: 'https://cdn.example.com/assets/', // CDN (always HTTPS) - publicPath: '//cdn.example.com/assets/', // CDN (same protocol) - publicPath: '/assets/', // server-relative - publicPath: 'assets/', // relative to HTML page - publicPath: '../assets/', // relative to HTML page - publicPath: '', // relative to HTML page (same directory) - } -}; -``` - -In cases where the `publicPath` of output files can't be known at compile time, it can be left blank and set dynamically at runtime in the entry file using the [free variable](https://stackoverflow.com/questions/12934929/what-are-free-variables) `__webpack_public_path__`. - -```javascript -__webpack_public_path__ = myRuntimePublicPath; - -// rest of your application entry -``` - -See [this discussion](https://github.com/webpack/webpack/issues/2776#issuecomment-233208623) for more information on `__webpack_public_path__`. - - -## `output.sourceMapFilename` - -`string` - -This option is only used when [`devtool`](/configuration/devtool) uses a SourceMap option which writes an output file. - -Configure how source maps are named. By default `'[file].map'` is used. - -The `[name]`, `[id]`, `[hash]` and `[chunkhash]` substitutions from [#output-filename](#output-filename) can be used. In addition to those, you can use substitutions listed below. The `[file]` placeholder is replaced with the filename of the original file. We recommend __only using the `[file]` placeholder__, as the other placeholders won't work when generating SourceMaps for non-chunk files. - -| Template | Description | -| -------------------------- | ----------------------------------------------------------------------------------- | -| [file] | The module filename | -| [filebase] | The module [basename](https://nodejs.org/api/path.html#path_path_basename_path_ext) | - - -## `output.sourcePrefix` - -`string` - -Change the prefix for each line in the output bundles. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - sourcePrefix: '\t' - } -}; -``` - -Note by default an empty string is used. Using some kind of indentation makes bundles look more pretty, but will cause issues with multi-line strings. - -There is no need to change it. - - -## `output.strictModuleExceptionHandling` - -`boolean` - -Tell webpack to remove a module from the module instance cache (`require.cache`) if it throws an exception when it is `require`d. - -It defaults to `false` for performance reasons. - -When set to `false`, the module is not removed from cache, which results in the exception getting thrown only on the first `require` call (making it incompatible with node.js). - -For instance, consider `module.js`: - -```javascript -throw new Error('error'); -``` - -With `strictModuleExceptionHandling` set to `false`, only the first `require` throws an exception: - -```javascript -// with strictModuleExceptionHandling = false -require('module'); // <- throws -require('module'); // <- doesn't throw -``` - -Instead, with `strictModuleExceptionHandling` set to `true`, all `require`s of this module throw an exception: - -```javascript -// with strictModuleExceptionHandling = true -require('module'); // <- throws -require('module'); // <- also throws -``` - - -## `output.umdNamedDefine` - -`boolean` - -When using `libraryTarget: "umd"`, setting: - -```javascript -module.exports = { - //... - output: { - umdNamedDefine: true - } -}; -``` - -will name the AMD module of the UMD build. Otherwise an anonymous `define` is used. - - -# Module - -These options determine how the [different types of modules](/concepts/modules) within a project will be treated. - - -## `module.noParse` - -`RegExp | [RegExp] | function | string | [string]` - -Prevent webpack from parsing any files matching the given regular expression(s). Ignored files __should not__ have calls to `import`, `require`, `define` or any other importing mechanism. This can boost build performance when ignoring large libraries. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - noParse: /jquery|lodash/, - } -}; -``` - -```javascript -module.exports = { - //... - module: { - noParse: (content) => /jquery|lodash/.test(content) - } -}; -``` - - -## `module.rules` - -`[Rule]` - -An array of [Rules](#rule) which are matched to requests when modules are created. These rules can modify how the module is created. They can apply loaders to the module, or modify the parser. - - -## Rule - -`object` - -A Rule can be separated into three parts — Conditions, Results and nested Rules. - - -### Rule Conditions - -There are two input values for the conditions: - -1. The resource: An absolute path to the file requested. It's already resolved according to the [`resolve` rules](/configuration/resolve). - -2. The issuer: An absolute path to the file of the module which requested the resource. It's the location of the import. - -__Example:__ When we `import './style.css'` within `app.js`, the resource is `/path/to/style.css` and the issuer is `/path/to/app.js`. - -In a Rule the properties [`test`](#rule-test), [`include`](#rule-include), [`exclude`](#rule-exclude) and [`resource`](#rule-resource) are matched with the resource and the property [`issuer`](#rule-issuer) is matched with the issuer. - -When using multiple conditions, all conditions must match. - -W> Be careful! The resource is the _resolved_ path of the file, which means symlinked resources are the real path _not_ the symlink location. This is good to remember when using tools that symlink packages (like `npm link`), common conditions like `/node_modules/` may inadvertently miss symlinked files. Note that you can turn off symlink resolving (so that resources are resolved to the symlink path) via [`resolve.symlinks`](/configuration/resolve#resolve-symlinks). - - -### Rule results - -Rule results are used only when the Rule condition matches. - -There are two output values of a Rule: - -1. Applied loaders: An array of loaders applied to the resource. -2. Parser options: An options object which should be used to create the parser for this module. - -These properties affect the loaders: [`loader`](#rule-loader), [`options`](#rule-options-rule-query), [`use`](#rule-use). - -For compatibility also these properties: [`query`](#rule-options-rule-query), [`loaders`](#rule-loaders). - -The [`enforce`](#rule-enforce) property affects the loader category. Whether it's a normal, pre- or post- loader. - -The [`parser`](#rule-parser) property affects the parser options. - - -## Nested rules - -Nested rules can be specified under the properties [`rules`](#rule-rules) and [`oneOf`](#rule-oneof). - -These rules are evaluated when the Rule condition matches. - - -## `Rule.enforce` - -`string` - -Possible values: `'pre' | 'post'` - -Specifies the category of the loader. No value means normal loader. - -There is also an additional category "inlined loader" which are loaders applied inline of the import/require. - -There are two phases that all loaders enter one after the other: - -1. __Pitching__ phase: the pitch method on loaders is called in the order `post, inline, normal, pre`. See [Pitching Loader](/api/loaders/#pitching-loader) for details. -2. __Normal__ phase: the normal method on loaders is executed in the order `pre, normal, inline, post`. Transformation on the source code of a module happens in this phase. - -All normal loaders can be omitted (overridden) by prefixing `!` in the request. - -All normal and pre loaders can be omitted (overridden) by prefixing `-!` in the request. - -All normal, post and pre loaders can be omitted (overridden) by prefixing `!!` in the request. - -Inline loaders and `!` prefixes should not be used as they are non-standard. They may be use by loader generated code. - - -## `Rule.exclude` - -`Rule.exclude` is a shortcut to `Rule.resource.exclude`. If you supply a `Rule.exclude` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.exclude`](#condition) for details. - - -## `Rule.include` - -`Rule.include` is a shortcut to `Rule.resource.include`. If you supply a `Rule.include` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.include`](#condition) for details. - - -## `Rule.issuer` - -A [`Condition`](#condition) to match against the module that issued the request. In the following example, the `issuer` for the `a.js` request would be the path to the `index.js` file. - -__index.js__ - -```javascript -import A from './a.js'; -``` - -This option can be used to apply loaders to the dependencies of a specific module or set of modules. - - -## `Rule.loader` - -`Rule.loader` is a shortcut to `Rule.use: [ { loader } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.loader`](#useentry) for details. - - -## `Rule.loaders` - -W> This option is __deprecated__ in favor of `Rule.use`. - -`Rule.loaders` is an alias to `Rule.use`. See [`Rule.use`](#rule-use) for details. - - -## `Rule.oneOf` - -An array of [`Rules`](#rule) from which only the first matching Rule is used when the Rule matches. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - oneOf: [ - { - resourceQuery: /inline/, // foo.css?inline - use: 'url-loader' - }, - { - resourceQuery: /external/, // foo.css?external - use: 'file-loader' - } - ] - } - ] - } -}; -``` - -## `Rule.options` / `Rule.query` - -`Rule.options` and `Rule.query` are shortcuts to `Rule.use: [ { options } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.options`](#useentry) for details. - -W> `Rule.query` is deprecated in favor of `Rule.options` and `UseEntry.options`. - - -## `Rule.parser` - -An object with parser options. All applied parser options are merged. - -Parsers may inspect these options and disable or reconfigure themselves accordingly. Most of the default plugins interpret the values as follows: - -- Setting the option to `false` disables the parser. -- Setting the option to `true` or leaving it `undefined` enables the parser. - -However, parser plugins may accept more than just a boolean. For example, the internal `NodeStuffPlugin` can accept an object instead of `true` to add additional options for a particular Rule. - -__Examples__ (parser options by the default plugins): - -```js-with-links -module.exports = { - //... - module: { - rules: [ - { - //... - parser: { - amd: false, // disable AMD - commonjs: false, // disable CommonJS - system: false, // disable SystemJS - harmony: false, // disable ES2015 Harmony import/export - requireInclude: false, // disable require.include - requireEnsure: false, // disable require.ensure - requireContext: false, // disable require.context - browserify: false, // disable special handling of Browserify bundles - requireJs: false, // disable requirejs.* - node: false, // disable __dirname, __filename, module, require.extensions, require.main, etc. - node: {...} // reconfigure [node](/configuration/node) layer on module level - } - } - ] - } -} -``` - - -## `Rule.resource` - -A [`Condition`](#condition) matched with the resource. You can either supply a `Rule.resource` option or use the shortcut options `Rule.test`, `Rule.exclude`, and `Rule.include`. See details in [`Rule` conditions](#rule-conditions). - - -## `Rule.resourceQuery` - -A [`Condition`](#condition) matched with the resource query. This option is used to test against the query section of a request string (i.e. from the question mark onwards). If you were to `import Foo from './foo.css?inline'`, the following condition would match: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - resourceQuery: /inline/, - use: 'url-loader' - } - ] - } -}; -``` - - -## `Rule.rules` - -An array of [`Rules`](#rule) that is also used when the Rule matches. - - -## `Rule.sideEffects` - -`bool` - -Indicate what parts of the module contain side effects. See [Tree Shaking](/guides/tree-shaking/#mark-the-file-as-side-effect-free) for details. - - -## `Rule.test` - -`Rule.test` is a shortcut to `Rule.resource.test`. If you supply a `Rule.test` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.test`](#condition) for details. - - -## `Rule.type` - -`string` - -Possible values: `'javascript/auto' | 'javascript/dynamic' | 'javascript/esm' | 'json' | 'webassembly/experimental'` - -`Rule.type` sets the type for a matching module. This prevents defaultRules and their default importing behaviors from occurring. For example, if you want to load a `.json` file through a custom loader, you'd need to set the `type` to `javascript/auto` to bypass webpack's built-in json importing. (See [v4.0 changelog](https://github.com/webpack/webpack/releases/tag/v4.0.0) for more details) - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - //... - { - test: /\.json$/, - type: 'javascript/auto', - loader: 'custom-json-loader' - } - ] - } -}; -``` - - -## `Rule.use` - -A list of [UseEntries](#useentry) which are applied to modules. Each entry specifies a loader to be used. - -Passing a string (i.e. `use: [ 'style-loader' ]`) is a shortcut to the loader property (i.e. `use: [ { loader: 'style-loader '} ]`). - -Loaders can be chained by passing multiple loaders, which will be applied from right to left (last to first configured). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - //... - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1 - } - }, - { - loader: 'less-loader', - options: { - noIeCompat: true - } - } - ] - } - ] - } -}; -``` - -See [UseEntry](#useentry) for details. - - -## `Condition` - -Conditions can be one of these: - -- A string: To match the input must start with the provided string. I. e. an absolute directory path, or absolute path to the file. -- A RegExp: It's tested with the input. -- A function: It's called with the input and must return a truthy value to match. -- An array of Conditions: At least one of the Conditions must match. -- An object: All properties must match. Each property has a defined behavior. - -`{ test: Condition }`: The Condition must match. The convention is to provide a RegExp or array of RegExps here, but it's not enforced. - -`{ include: Condition }`: The Condition must match. The convention is to provide a string or array of strings here, but it's not enforced. - -`{ exclude: Condition }`: The Condition must NOT match. The convention is to provide a string or array of strings here, but it's not enforced. - -`{ and: [Condition] }`: All Conditions must match. - -`{ or: [Condition] }`: Any Condition must match. - -`{ not: [Condition] }`: All Conditions must NOT match. - -__Example:__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - include: [ - path.resolve(__dirname, 'app/styles'), - path.resolve(__dirname, 'vendor/styles') - ] - } - ] - } -}; -``` - - -## `UseEntry` - -`object` - -It must have a `loader` property being a string. It is resolved relative to the configuration [`context`](/configuration/entry-context#context) with the loader resolving options ([resolveLoader](/configuration/resolve#resolveloader)). - -It can have an `options` property being a string or object. This value is passed to the loader, which should interpret it as loader options. - -For compatibility a `query` property is also possible, which is an alias for the `options` property. Use the `options` property instead. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - loader: 'css-loader', - options: { - modules: true - } - } - ] - } -}; -``` - -Note that webpack needs to generate a unique module identifier from the resource and all loaders including options. It tries to do this with a `JSON.stringify` of the options object. This is fine in 99.9% of cases, but may be not unique if you apply the same loaders with different options to the resource and the options have some stringified values. - -It also breaks if the options object cannot be stringified (i.e. circular JSON). Because of this you can have a `ident` property in the options object which is used as unique identifier. - - -## Module Contexts - -> Avoid using these options as they are __deprecated__ and will soon be removed. - -These options describe the default settings for the context created when a dynamic dependency is encountered. - -Example for an `unknown` dynamic dependency: `require`. - -Example for an `expr` dynamic dependency: `require(expr)`. - -Example for an `wrapped` dynamic dependency: `require('./templates/' + expr)`. - -Here are the available options with their [defaults](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js): - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - exprContextCritical: true, - exprContextRecursive: true, - exprContextRegExp: false, - exprContextRequest: '.', - unknownContextCritical: true, - unknownContextRecursive: true, - unknownContextRegExp: false, - unknownContextRequest: '.', - wrappedContextCritical: false, - wrappedContextRecursive: true, - wrappedContextRegExp: /.*/, - strictExportPresence: false // since webpack 2.3.0 - } -}; -``` - -T> You can use the `ContextReplacementPlugin` to modify these values for individual dependencies. This also removes the warning. - -A few use cases: - -- Warn for dynamic dependencies: `wrappedContextCritical: true`. -- `require(expr)` should include the whole directory: `exprContextRegExp: /^\.\//` -- `require('./templates/' + expr)` should not include subdirectories by default: `wrappedContextRecursive: false` -- `strictExportPresence` makes missing exports an error instead of warning - - -# Resolve - -These options change how modules are resolved. webpack provides reasonable defaults, but it is possible to change the resolving in detail. Have a look at [Module Resolution](/concepts/module-resolution) for more explanation of how the resolver works. - - -## `resolve` - -`object` - -Configure how modules are resolved. For example, when calling `import "lodash"` in ES2015, the `resolve` options can change where webpack goes to look for `"lodash"` (see [`modules`](#resolve-modules)). - - -### `resolve.alias` - -`object` - -Create aliases to `import` or `require` certain modules more easily. For example, to alias a bunch of commonly used `src/` folders: - -```js -module.exports = { - //... - resolve: { - alias: { - Utilities: path.resolve(__dirname, 'src/utilities/'), - Templates: path.resolve(__dirname, 'src/templates/') - } - } -}; -``` - -Now, instead of using relative paths when importing like so: - -```js -import Utility from '../../utilities/utility'; -``` - -you can use the alias: - -```js -import Utility from 'Utilities/utility'; -``` - -A trailing `$` can also be added to the given object's keys to signify an exact match: - -```js -module.exports = { - //... - resolve: { - alias: { - xyz$: path.resolve(__dirname, 'path/to/file.js') - } - } -}; -``` - -which would yield these results: - -```js -import Test1 from 'xyz'; // Exact match, so path/to/file.js is resolved and imported -import Test2 from 'xyz/file.js'; // Not an exact match, normal resolution takes place -``` - -The following table explains other cases: - -| `alias:` | `import "xyz"` | `import "xyz/file.js"` | -| ----------------------------------- | ------------------------------------- | ----------------------------------- | -| `{}` | `/abc/node_modules/xyz/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | error | -| `{ xyz$: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "./dir/file.js" }` | `/abc/dir/file.js` | error | -| `{ xyz$: "./dir/file.js" }` | `/abc/dir/file.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "/some/dir" }` | `/some/dir/index.js` | `/some/dir/file.js` | -| `{ xyz$: "/some/dir" }` | `/some/dir/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "./dir" }` | `/abc/dir/index.js` | `/abc/dir/file.js` | -| `{ xyz: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/modu/file.js` | -| `{ xyz$: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "modu/some/file.js" }` | `/abc/node_modules/modu/some/file.js` | error | -| `{ xyz: "modu/dir" }` | `/abc/node_modules/modu/dir/index.js` | `/abc/node_modules/dir/file.js` | -| `{ xyz: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/dir/file.js` | -| `{ xyz$: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/file.js` | - -`index.js` may resolve to another file if defined in the `package.json`. - -`/abc/node_modules` may resolve in `/node_modules` too. - - -### `resolve.aliasFields` - -`array` - -Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec). Default: - -```js -module.exports = { - //... - resolve: { - aliasFields: ['browser'] - } -}; -``` - - -### `resolve.cacheWithContext` - -`boolean` (since webpack 3.1.0) - -If unsafe cache is enabled, includes `request.context` in the cache key. This option is taken into account by the [`enhanced-resolve`](https://github.com/webpack/enhanced-resolve/) module. Since webpack 3.1.0 context in resolve caching is ignored when resolve or resolveLoader plugins are provided. This addresses a performance regression. - - -### `resolve.descriptionFiles` - -`array` - -The JSON files to use for descriptions. Default: - -```js -module.exports = { - //... - resolve: { - descriptionFiles: ['package.json'] - } -}; -``` - - -### `resolve.enforceExtension` - -`boolean` - -If `true`, it will not allow extension-less files. So by default `require('./foo')` works if `./foo` has a `.js` extension, but with this enabled only `require('./foo.js')` will work. Default: - -```js -module.exports = { - //... - resolve: { - enforceExtension: false - } -}; -``` - - -### `resolve.enforceModuleExtension` - -`boolean` - -Whether to require to use an extension for modules (e.g. loaders). Default: - -```js -module.exports = { - //... - resolve: { - enforceModuleExtension: false - } -}; -``` - - -### `resolve.extensions` - -`array` - -Automatically resolve certain extensions. This defaults to: - -```js -module.exports = { - //... - resolve: { - extensions: ['.wasm', '.mjs', '.js', '.json'] - } -}; -``` - -which is what enables users to leave off the extension when importing: - -```js -import File from '../path/to/file'; -``` - -W> Using this will __override the default array__, meaning that webpack will no longer try to resolve modules using the default extensions. For modules that are imported with their extension, e.g. `import SomeFile from "./somefile.ext"`, to be properly resolved, a string containing "\*" must be included in the array. - - -### `resolve.mainFields` - -`array` - -When importing from an npm package, e.g. `import * as D3 from "d3"`, this option will determine which fields in its `package.json` are checked. The default values will vary based upon the [`target`](/concepts/targets) specified in your webpack configuration. - -When the `target` property is set to `webworker`, `web`, or left unspecified: - - -```js -module.exports = { - //... - resolve: { - mainFields: ['browser', 'module', 'main'] - } -}; -``` - -For any other target (including `node`): - -```js -module.exports = { - //... - resolve: { - mainFields: ['module', 'main'] - } -}; -``` - -For example, the `package.json` of [D3](https://d3js.org/) contains these fields: - -```json -{ - "main": "build/d3.Node.js", - "browser": "build/d3.js", - "module": "index" -} -``` - -This means that when we `import * as D3 from "d3"` this will really resolve to the file in the `browser` property. The `browser` property takes precedence here because it's the first item in `mainFields`. Meanwhile, a Node.js application bundled by webpack will resolve by default to the file in the `module` field. - - -### `resolve.mainFiles` - -`array` - -The filename to be used while resolving directories. Default: - -```js -module.exports = { - //... - resolve: { - mainFiles: ['index'] - } -}; -``` - - -### `resolve.modules` - -`array` - -Tell webpack what directories should be searched when resolving modules. - -Absolute and relative paths can both be used, but be aware that they will behave a bit differently. - -A relative path will be scanned similarly to how Node scans for `node_modules`, by looking through the current directory as well as its ancestors (i.e. `./node_modules`, `../node_modules`, and on). - -With an absolute path, it will only search in the given directory. - -`resolve.modules` defaults to: - -```js -module.exports = { - //... - resolve: { - modules: ['node_modules'] - } -}; -``` - -If you want to add a directory to search in that takes precedence over `node_modules/`: - -```js -module.exports = { - //... - resolve: { - modules: [path.resolve(__dirname, 'src'), 'node_modules'] - } -}; -``` - - -### `resolve.unsafeCache` - -`regex` `array` `boolean` - -Enable aggressive, but __unsafe__, caching of modules. Passing `true` will cache everything. Default: - -```js -module.exports = { - //... - resolve: { - unsafeCache: true - } -}; -``` - -A regular expression, or an array of regular expressions, can be used to test file paths and only cache certain modules. For example, to only cache utilities: - -```js -module.exports = { - //... - resolve: { - unsafeCache: /src\/utilities/ - } -}; -``` - -W> Changes to cached paths may cause failure in rare cases. - - -### `resolve.plugins` - -A list of additional resolve plugins which should be applied. It allows plugins such as [`DirectoryNamedWebpackPlugin`](https://www.npmjs.com/package/directory-named-webpack-plugin). - -```js -module.exports = { - //... - resolve: { - plugins: [ - new DirectoryNamedWebpackPlugin() - ] - } -}; -``` - - -### `resolve.symlinks` - -`boolean` - -Whether to resolve symlinks to their symlinked location. - -When enabled, symlinked resources are resolved to their _real_ path, not their symlinked location. Note that this may cause module resolution to fail when using tools that symlink packages (like `npm link`). - -`resolve.symlinks` defaults to: - -```js -module.exports = { - //... - resolve: { - symlinks: true - } -}; -``` - - -### `resolve.cachePredicate` - -`function` - -A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. Default: - -```js -module.exports = { - //... - resolve: { - cachePredicate: function() { return true; } - } -}; -``` - - -## `resolveLoader` - -`object` - -This set of options is identical to the `resolve` property set above, but is used only to resolve webpack's [loader](/concepts/loaders) packages. Default: - -```js -module.exports = { - //... - resolveLoader: { - modules: [ 'node_modules' ], - extensions: [ '.js', '.json' ], - mainFields: [ 'loader', 'main' ] - } -}; -``` - -T> Note that you can use alias here and other features familiar from resolve. For example `{ txt: 'raw-loader' }` would shim `txt!templates/demo.txt` to use `raw-loader`. - - -### `resolveLoader.moduleExtensions` - -`array` - -The extensions/suffixes that are used when resolving loaders. Since version two, we [strongly recommend](/migrate/3/#automatic-loader-module-name-extension-removed) using the full name, e.g. `example-loader`, as much as possible for clarity. However, if you really wanted to exclude the `-loader` bit, i.e. just use `example`, you can use this option to do so: - -```js -module.exports = { - //... - resolveLoader: { - moduleExtensions: [ '-loader' ] - } -}; -``` - - -# Optimization - -Since version 4 webpack runs optimizations for you depending on the chosen [`mode`](/concepts/mode/), still all optimizations are available for manual configuration and overrides. - - -## `optimization.minimize` - -`boolean` - -Tell webpack to minimize the bundle using the [TerserPlugin](/plugins/terser-webpack-plugin/). - -This is `true` by default in `production` mode. - -__webpack.config.js__ - - -```js -module.exports = { - //... - optimization: { - minimize: false - } -}; -``` - -T> Learn how [mode](/concepts/mode/) works. - -## `optimization.minimizer` - -`[TerserPlugin]` - -Allows you to override the default minimizer by providing a different one or more customized [TerserPlugin](/plugins/terser-webpack-plugin/) instances. - -__webpack.config.js__ - - -```js -const TerserPlugin = require('terser-webpack-plugin'); - -module.exports = { - //... - optimization: { - minimizer: [ - new TerserPlugin({ /* your config */ }) - ] - } -}; -``` - -## `optimization.splitChunks` - -`object` - -By default webpack v4+ provides new common chunks strategies out of the box for dynamically imported modules. See available options for configuring this behavior in the [SplitChunksPlugin](/plugins/split-chunks-plugin/) page. - -## `optimization.runtimeChunk` - -`object` `string` `boolean` - -Setting `optimization.runtimeChunk` to `true` or `"multiple"` adds an additional chunk to each entrypoint containing only the runtime. This setting is an alias for: - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: entrypoint => `runtime~${entrypoint.name}` - } - } -}; -``` - -The value `"single"` instead creates a runtime file to be shared for all generated chunks. This setting is an alias for: - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: 'runtime' - } - } -}; -``` - -By setting `optimization.runtimeChunk` to `object` it is only possible to provide the `name` property which stands for the name or name factory for the runtime chunks. - -Default is `false`: each entry chunk embeds runtime. - -W> Imported modules are initialized for each runtime chunk separately, so if you include multiple entry points on a page, beware of this behavior. You will probably want to set it to `single` or use another configuration that allows you to only have one runtime instance. - -__webpack.config.js__ - - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: entrypoint => `runtimechunk~${entrypoint.name}` - } - } -}; -``` - -## `optimization.noEmitOnErrors` - -`boolean` - -Use the `optimization.noEmitOnErrors` to skip the emitting phase whenever there are errors while compiling. This ensures that no erroring assets are emitted. The `emitted` flag in the stats is `false` for all assets. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - noEmitOnErrors: true - } -}; -``` - -W> If you are using webpack [CLI](/api/cli/), the webpack process will not exit with an error code while this plugin is enabled. If you want webpack to "fail" when using the CLI, please check out the [`bail` option](/api/cli/#advanced-options). - -## `optimization.namedModules` - -`boolean: false` - -Tells webpack to use readable module identifiers for better debugging. When `optimization.namedModules` is not set in webpack config, webpack will enable it by default for [mode](/concepts/mode/) `development` and disable for [mode](/concepts/mode/) `production`. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - namedModules: true - } -}; -``` - -## `optimization.namedChunks` - -`boolean: false` - -Tells webpack to use readable chunk identifiers for better debugging. This option is enabled by default for [mode](/concepts/mode/) `development` and disabled for [mode](/concepts/mode/) `production` if no option is provided in webpack config. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - namedChunks: true - } -}; -``` - -## `optimization.moduleIds` - -`bool: false` `string: natural, named, hashed, size, total-size` - -Tells webpack which algorithm to use when choosing module ids. Setting `optimization.moduleIds` to `false` tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin. By default `optimization.moduleIds` is set to `false`. - -The following string values are supported: - -Option | Description ---------------------- | ----------------------- -`natural` | Numeric ids in order of usage. -`named` | Readable ids for better debugging. -`hashed` | Short hashes as ids for better long term caching. -`size` | Numeric ids focused on minimal initial download size. -`total-size` | numeric ids focused on minimal total download size. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - moduleIds: 'hashed' - } -}; -``` - -## `optimization.nodeEnv` - -`string` `bool: false` - -Tells webpack to set `process.env.NODE_ENV` to a given string value. `optimization.nodeEnv` uses [DefinePlugin](/plugins/define-plugin/) unless set to `false`. `optimization.nodeEnv` __defaults__ to [mode](/concepts/mode/) if set, else falls back to `"production"`. - -Possible values: - -- any string: the value to set `process.env.NODE_ENV` to. -- false: do not modify/set the value of `process.env.NODE_ENV`. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - nodeEnv: 'production' - } -}; -``` - -## `optimization.mangleWasmImports` - -`bool: false` - -When set to `true` tells webpack to reduce the size of WASM by changing imports to shorter strings. It mangles module and export names. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - mangleWasmImports: true - } -}; -``` - -## `optimization.removeAvailableModules` - -`bool: true` - -Tells webpack to detect and remove modules from chunks when these modules are already included in all parents. Setting `optimization.removeAvailableModules` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - removeAvailableModules: false - } -}; -``` - -## `optimization.removeEmptyChunks` - -`bool: true` - -Tells webpack to detect and remove chunks which are empty. Setting `optimization.removeEmptyChunks` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - removeEmptyChunks: false - } -}; -``` - -## `optimization.mergeDuplicateChunks` - -`bool: true` - -Tells webpack to merge chunks which contain the same modules. Setting `optimization.mergeDuplicateChunks` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - mergeDuplicateChunks: false - } -}; -``` - -## `optimization.flagIncludedChunks` - -`bool` - -Tells webpack to determine and flag chunks which are subsets of other chunks in a way that subsets don’t have to be loaded when the bigger chunk has been already loaded. By default `optimization.flagIncludedChunks` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - flagIncludedChunks: true - } -}; -``` - -## `optimization.occurrenceOrder` - -`bool` - -Tells webpack to figure out an order of modules which will result in the smallest initial bundle. By default `optimization.occurrenceOrder` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - occurrenceOrder: false - } -}; -``` - -## `optimization.providedExports` - -`bool` - -Tells webpack to figure out which exports are provided by modules to generate more efficient code for `export * from ...`. By default `optimization.providedExports` is enabled. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - providedExports: false - } -}; -``` - -## `optimization.usedExports` - -`bool` - -Tells webpack to determine used exports for each module. This depends on [`optimization.providedExports`](#optimization-occurrenceorder). Information collected by `optimization.usedExports` is used by other optimizations or code generation i.e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible. -Dead code elimination in minimizers will benefit from this and can remove unused exports. -By default `optimization.usedExports` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - usedExports: true - } -}; -``` - -## `optimization.concatenateModules` - -`bool` - -Tells webpack to find segments of the module graph which can be safely concatenated into a single module. Depends on [`optimization.providedExports`](#optimization-providedexports) and [`optimization.usedExports`](#optimization-usedexports). -By default `optimization.concatenateModules` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - concatenateModules: true - } -}; -``` - -## `optimization.sideEffects` - -`bool` - -Tells webpack to recognise the [`sideEffects`](https://github.com/webpack/webpack/blob/master/examples/side-effects/README.md) flag in `package.json` or rules to skip over modules which are flagged to contain no side effects when exports are not used. - -__package.json__ - -``` json -{ - "name": "awesome npm module", - "version": "1.0.0", - "sideEffects": false -} -``` - -T> Please note that `sideEffects` should be in the npm module's `package.json` file and doesn't mean that you need to set `sideEffects` to `false` in your own project's `package.json` which requires that big module. - -`optimization.sideEffects` depends on [`optimization.providedExports`](#optimization-providedexports) to be enabled. This dependency has a build time cost, but eliminating modules has positive impact on performance because of less code generation. Effect of this optimization depends on your codebase, try it for possible performance wins. - -By default `optimization.sideEffects` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - sideEffects: true - } -}; -``` - -## `optimization.portableRecords` - -`bool` - -`optimization.portableRecords` tells webpack to generate records with relative paths to be able to move the context folder. - -By default `optimization.portableRecords` is disabled. Automatically enabled if at least one of the records options provided to webpack config: [`recordsPath`](/configuration/other-options/#recordspath), [`recordsInputPath`](/configuration/other-options/#recordsinputpath), [`recordsOutputPath`](/configuration/other-options/#recordsoutputpath). - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - portableRecords: true - } -}; -``` - - -# Plugins - -The `plugins` option is used to customize the webpack build process in a variety of ways. webpack comes with a variety built-in plugins available under `webpack.[plugin-name]`. See [Plugins page](/plugins) for a list of plugins and documentation but note that there are a lot more out in the community. - -T> Note: This page only discusses using plugins, however if you are interested in writing your own please visit [Writing a Plugin](/development/how-to-write-a-plugin/). - - -## `plugins` - -`array` - -A list of webpack plugins. For example, [`DefinePlugin`](/plugins/define-plugin/) allows you to create global constants which can be configured at compile time. This can be useful for allowing different behavior between development builds and release builds. - -```js -module.exports = { - //... - plugins: [ - new webpack.DefinePlugin({ - // Definitions... - }) - ] -}; -``` - -A more complex example, using multiple plugins, might look something like this: - -```js -var webpack = require('webpack'); -// importing plugins that do not come by default in webpack -var ExtractTextPlugin = require('extract-text-webpack-plugin'); -var DashboardPlugin = require('webpack-dashboard/plugin'); - -// adding plugins to your configuration -module.exports = { - //... - plugins: [ - new ExtractTextPlugin({ - filename: 'build.min.css', - allChunks: true, - }), - new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), - // compile time plugins - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': '"production"', - }), - // webpack-dev-server enhancement plugins - new DashboardPlugin(), - new webpack.HotModuleReplacementPlugin(), - ] -}; -``` - - -# DevServer - -[webpack-dev-server](https://github.com/webpack/webpack-dev-server) can be used to quickly develop an application. See the [development guide](/guides/development/) to get started. - -This page describes the options that affect the behavior of webpack-dev-server (short: dev-server). - -T> Options that are compatible with [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) have 🔑 next to them. - - -## `devServer` - -`object` - -This set of options is picked up by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) and can be used to change its behavior in various ways. Here's a simple example that gzips and serves everything from our `dist/` directory in the project root: - -__webpack.config.js__ - -```javascript -var path = require('path'); - -module.exports = { - //... - devServer: { - contentBase: path.join(__dirname, 'dist'), - compress: true, - port: 9000 - } -}; -``` - -When the server is started, there will be a message prior to the list of resolved modules: - -```bash -http://localhost:9000/ -webpack output is served from /build/ -Content not from webpack is served from /path/to/dist/ -``` - -that will give some background on where the server is located and what it's serving. - -If you're using dev-server through the Node.js API, the options in `devServer` will be ignored. Pass the options as a second parameter instead: `new WebpackDevServer(compiler, {...})`. [See here](https://github.com/webpack/webpack-dev-server/tree/master/examples/api/simple) for an example of how to use webpack-dev-server through the Node.js API. - -W> Be aware that when [exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) only the `devServer` options for the first configuration will be taken into account and used for all the configurations in the array. - -T> If you're having trouble, navigating to the `/webpack-dev-server` route will show where files are served. For example, `http://localhost:9000/webpack-dev-server`. - -## `devServer.after` - -`function (app, server)` - -Provides the ability to execute custom middleware after all other middleware -internally within the server. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - after: function(app, server) { - // do fancy stuff - } - } -}; -``` - -## `devServer.allowedHosts` - -`array` - -This option allows you to whitelist services that are allowed to access the dev server. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - allowedHosts: [ - 'host.com', - 'subdomain.host.com', - 'subdomain2.host.com', - 'host2.com' - ] - } -}; -``` - -Mimicking django's `ALLOWED_HOSTS`, a value beginning with `.` can be used as a subdomain wildcard. `.host.com` will match `host.com`, `www.host.com`, and any other subdomain of `host.com`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - // this achieves the same effect as the first example - // with the bonus of not having to update your config - // if new subdomains need to access the dev server - allowedHosts: [ - '.host.com', - 'host2.com' - ] - } -}; -``` - -To use this option with the CLI pass the `--allowed-hosts` option a comma-delimited string. - -```bash -webpack-dev-server --entry /entry/file --output-path /output/path --allowed-hosts .host.com,host2.com -``` - -## `devServer.before` - -`function (app, server)` - -Provides the ability to execute custom middleware prior to all other middleware -internally within the server. This could be used to define custom handlers, for -example: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - before: function(app, server) { - app.get('/some/path', function(req, res) { - res.json({ custom: 'response' }); - }); - } - } -}; -``` - -## `devServer.bonjour` - -This option broadcasts the server via [ZeroConf](http://www.zeroconf.org/) networking on start - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - bonjour: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --bonjour -``` - - -## `devServer.clientLogLevel` - -`string: 'none' | 'info' | 'error' | 'warning'` - -When using _inline mode_, the console in your DevTools will show you messages e.g. before reloading, before an error or when [Hot Module Replacement](/concepts/hot-module-replacement/) is enabled. Defaults to `info`. - -`devServer.clientLogLevel` may be too verbose, you can turn logging off by setting it to `'none'`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - clientLogLevel: 'none' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --client-log-level none -``` - -## `devServer.color` - CLI only - -`boolean` - -Enables/Disables colors on the console. - -```bash -webpack-dev-server --color -``` - - -## `devServer.compress` - -`boolean` - -Enable [gzip compression](https://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/) for everything served: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - compress: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --compress -``` - - -## `devServer.contentBase` - -`boolean: false` `string` `[string]` `number` - -Tell the server where to serve content from. This is only necessary if you want to serve static files. [`devServer.publicPath`](#devserver-publicpath-) will be used to determine where the bundles should be served from, and takes precedence. - -T> It is recommended to use an absolute path. - -By default it will use your current working directory to serve content. To disable `contentBase` set it to `false`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - contentBase: path.join(__dirname, 'public') - } -}; -``` - -It is also possible to serve from multiple directories: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - contentBase: [path.join(__dirname, 'public'), path.join(__dirname, 'assets')] - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --content-base /path/to/content/dir -``` - - -## `devServer.disableHostCheck` - -`boolean` - -When set to `true` this option bypasses host checking. __THIS IS NOT RECOMMENDED__ as apps that do not check the host are vulnerable to DNS rebinding attacks. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - disableHostCheck: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --disable-host-check -``` - - -## `devServer.filename` 🔑 - -`string` - -This option lets you reduce the compilations in [lazy mode](#devserver-lazy-). -By default in [lazy mode](#devserver-lazy-), every request results in a new compilation. With `filename`, it's possible to only compile when a certain file is requested. - -If [`output.filename`](/configuration/output/#output-filename) is set to `'bundle.js'` and `devServer.filename` is used like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: 'bundle.js' - }, - devServer: { - lazy: true, - filename: 'bundle.js' - } -}; -``` - -It will now only compile the bundle when `/bundle.js` is requested. - -T> `filename` has no effect when used without [lazy mode](#devserver-lazy-). - - -## `devServer.headers` 🔑 - -`object` - -Adds headers to all responses: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - headers: { - 'X-Custom-Foo': 'bar' - } - } -}; -``` - - -## `devServer.historyApiFallback` - -`boolean` `object` - -When using the [HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/API/History), the `index.html` page will likely have to be served in place of any `404` responses. `devServer.historyApiFallback` is disabled by default. Enable it by passing: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: true - } -}; -``` - -By passing an object this behavior can be controlled further using options like `rewrites`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: { - rewrites: [ - { from: /^\/$/, to: '/views/landing.html' }, - { from: /^\/subpage/, to: '/views/subpage.html' }, - { from: /./, to: '/views/404.html' } - ] - } - } -}; -``` - -When using dots in your path (common with Angular), you may need to use the `disableDotRule`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: { - disableDotRule: true - } - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --history-api-fallback -``` - -For more options and information, see the [connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback) documentation. - - -## `devServer.host` - -`string` - -Specify a host to use. By default this is `localhost`. If you want your server to be accessible externally, specify it like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - host: '0.0.0.0' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --host 0.0.0.0 -``` - - -## `devServer.hot` - -`boolean` - -Enable webpack's [Hot Module Replacement](/concepts/hot-module-replacement/) feature: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - hot: true - } -}; -``` - -T> Note that [`webpack.HotModuleReplacementPlugin`](/plugins/hot-module-replacement-plugin/) is required to fully enable HMR. If `webpack` or `webpack-dev-server` are launched with the `--hot` option, this plugin will be added automatically, so you may not need to add this to your `webpack.config.js`. See the [HMR concepts page](/concepts/hot-module-replacement/) for more information. - - -## `devServer.hotOnly` - -`boolean` - -Enables Hot Module Replacement (see [`devServer.hot`](#devserver-hot)) without page refresh as fallback in case of build failures. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - hotOnly: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --hot-only -``` - - -## `devServer.https` - -`boolean` `object` - -By default dev-server will be served over HTTP. It can optionally be served over HTTP/2 with HTTPS: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - https: true - } -}; -``` - -With the above setting a self-signed certificate is used, but you can provide your own: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - https: { - key: fs.readFileSync('/path/to/server.key'), - cert: fs.readFileSync('/path/to/server.crt'), - ca: fs.readFileSync('/path/to/ca.pem'), - } - } -}; -``` - -This object is passed straight to Node.js HTTPS module, so see the [HTTPS documentation](https://nodejs.org/api/https.html) for more information. - -Usage via the CLI - -```bash -webpack-dev-server --https -``` - -To pass your own certificate via the CLI use the following options - -```bash -webpack-dev-server --https --key /path/to/server.key --cert /path/to/server.crt --cacert /path/to/ca.pem -``` - -## `devServer.index` - -`string` - -The filename that is considered the index file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - index: 'index.html' - } -}; -``` - - -## `devServer.info` - CLI only - -`boolean` - -Output cli information. It is enabled by default. - -```bash -webpack-dev-server --info=false -``` - - -## `devServer.inline` - -`boolean` - -Toggle between the dev-server's two different modes. By default the application will be served with _inline mode_ enabled. This means that a script will be inserted in your bundle to take care of live reloading, and build messages will appear in the browser console. - -It is also possible to use __iframe mode__, which uses an `<iframe>` under a notification bar with messages about the build. To switch to __iframe mode__: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - inline: false - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --inline=false -``` - -T> Inline mode is recommended for [Hot Module Replacement](/plugins/hot-module-replacement-plugin/) as it includes an HMR trigger from the websocket. Polling mode can be used as an alternative, but requires an additional entry point, `'webpack/hot/poll?1000'`. - - -## `devServer.lazy` 🔑 - -`boolean` - -When `devServer.lazy` is enabled, the dev-server will only compile the bundle when it gets requested. This means that webpack will not watch any file changes. We call this __lazy mode__. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - lazy: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --lazy -``` - -T> [`watchOptions`](#devserver-watchoptions-) will have no effect when used with __lazy mode__. - -T> If you use the CLI, make sure __inline mode__ is disabled. - - -## `devServer.noInfo` 🔑 - -`boolean` - -Tells dev-server to supress messages like the webpack bundle information. Errors and warnings will still be shown. `devServer.noInfo` is disabled by default. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - noInfo: true - } -}; -``` - - -## `devServer.open` - -`boolean` `string` - -Tells dev-server to open the browser after server had been started. Disabled by default. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - open: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --open -``` - -If no browser is provided (as shown above), your default browser will be used. To specify a different browser, just pass its name: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - open: 'Chrome' - } -}; -``` - -And via the CLI - -```bash -webpack-dev-server --open 'Chrome' -``` - -T> The browser application name is platform dependent. Don't hard code it in reusable modules. For example, `'Chrome'` is Google Chrome on macOS, `'google-chrome'` on Linux and `'chrome'` on Windows. - - -## `devServer.openPage` - -`string` - -Specify a page to navigate to when opening the browser. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - openPage: '/different/page' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --open-page "/different/page" -``` - - -## `devServer.overlay` - -`boolean` `object: { boolean errors, boolean warnings }` - -Shows a full-screen overlay in the browser when there are compiler errors or warnings. Disabled by default. If you want to show only compiler errors: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - overlay: true - } -}; -``` - -If you want to show warnings as well as errors: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - overlay: { - warnings: true, - errors: true - } - } -}; -``` - - -## `devServer.pfx` - -`string` - -When used via the CLI, a path to an SSL .pfx file. If used in options, it should be the bytestream of the .pfx file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - pfx: '/path/to/file.pfx' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --pfx /path/to/file.pfx -``` - - -## `devServer.pfxPassphrase` - -`string` - -The passphrase to a SSL PFX file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - pfxPassphrase: 'passphrase' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --pfx-passphrase passphrase -``` - - -## `devServer.port` - -`number` - -Specify a port number to listen for requests on: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - port: 8080 - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --port 8080 -``` - - -## `devServer.proxy` - -`object` `[object, function]` - -Proxying some URLs can be useful when you have a separate API backend development server and you want to send API requests on the same domain. - -The dev-server makes use of the powerful [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) package. Check out its [documentation](https://github.com/chimurai/http-proxy-middleware#options) for more advanced usages. Note that some of `http-proxy-middleware`'s features do not require a `target` key, e.g. its `router` feature, but you will still need to include a `target` key in your config here, otherwise `webpack-dev-server` won't pass it along to `http-proxy-middleware`). - -With a backend on `localhost:3000`, you can use this to enable proxying: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': 'http://localhost:3000' - } - } -}; -``` - -A request to `/api/users` will now proxy the request to `http://localhost:3000/api/users`. - -If you don't want `/api` to be passed along, we need to rewrite the path: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'http://localhost:3000', - pathRewrite: {'^/api' : ''} - } - } - } -}; -``` - -A backend server running on HTTPS with an invalid certificate will not be accepted by default. If you want to, modify your config like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'https://other-server.example.com', - secure: false - } - } - } -}; -``` - -Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a function. - -In the function you get access to the request, response and proxy options. It must return either `false` or a path that will be served instead of continuing to proxy the request. - -E.g. for a browser request, you want to serve a HTML page, but for an API request you want to proxy it. You could do something like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'http://localhost:3000', - bypass: function(req, res, proxyOptions) { - if (req.headers.accept.indexOf('html') !== -1) { - console.log('Skipping proxy for browser request.'); - return '/index.html'; - } - } - } - } - } -}; -``` - -If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a `context` property: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: [{ - context: ['/auth', '/api'], - target: 'http://localhost:3000', - }] - } -}; -``` - -Note that requests to root won't be proxied by default. To enable root proxying, the `devServer.index` option should be specified as a falsy value: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - index: '', // specify to enable root proxying - host: '...', - contentBase: '...', - proxy: { - context: () => true, - target: 'http://localhost:1234' - } - } -}; -``` - -The origin of the host header is kept when proxying by default, you can set `changeOrigin` to `true` to override this behaviour. It is useful in some cases like using [name-based virtual hosted sites](https://en.wikipedia.org/wiki/Virtual_hosting#Name-based). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': 'http://localhost:3000', - changeOrigin: true - } - } -}; -``` - -## `devServer.progress` - CLI only - -`boolean` - -Output running progress to console. - -```bash -webpack-dev-server --progress -``` - - -## `devServer.public` - -`string` - -When using _inline mode_ and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on `window.location`, but if that fails you'll need to use this. - -For example, the dev-server is proxied by nginx, and available on `myapp.test`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - public: 'myapp.test:80' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --public myapp.test:80 -``` - - -## `devServer.publicPath` 🔑 - -`string` - -The bundled files will be available in the browser under this path. - -Imagine that the server is running under `http://localhost:8080` and [`output.filename`](/configuration/output/#output-filename) is set to `bundle.js`. By default the `devServer.publicPath` is `'/'`, so your bundle is available as `http://localhost:8080/bundle.js`. - -Change `devServer.publicPath` to put bundle under specific directory: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - publicPath: '/assets/' - } -}; -``` - -The bundle will now be available as `http://localhost:8080/assets/bundle.js`. - -T> Make sure `devServer.publicPath` always starts and ends with a forward slash. - -It is also possible to use a full URL. This is necessary for [Hot Module Replacement](/concepts/hot-module-replacement/). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - publicPath: 'http://localhost:8080/assets/' - } -}; -``` - -The bundle will also be available as `http://localhost:8080/assets/bundle.js`. - -T> It is recommended that `devServer.publicPath` is the same as [`output.publicPath`](/configuration/output/#output-publicpath). - - -## `devServer.quiet` 🔑 - -`boolean` - -With `devServer.quiet` enabled, nothing except the initial startup information will be written to the console. This also means that errors or warnings from webpack are not visible. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - quiet: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --quiet -``` - - -## `devServer.setup` - -`function (app, server)` - -W> This option is __deprecated__ in favor of [`devServer.before`](#devserver-before) and will be removed in v3.0.0. - -Here you can access the Express app object and add your own custom middleware to it. -For example, to define custom handlers for some paths: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - setup: function(app, server) { - app.get('/some/path', function(req, res) { - res.json({ custom: 'response' }); - }); - } - } -}; -``` - - -## `devServer.socket` - -`string` - -The Unix socket to listen to (instead of a host). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - socket: 'socket' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --socket socket -``` - - -## `devServer.staticOptions` - -It is possible to configure advanced options for serving static files from `contentBase`. See the [Express documentation](http://expressjs.com/en/4x/api.html#express.static) for the possible options. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - staticOptions: { - redirect: false - } - } -}; -``` - -T> This only works when using [`devServer.contentBase`](#devserver-contentbase) as a `string`. - - -## `devServer.stats` 🔑 - -`string: 'none' | 'errors-only' | 'minimal' | 'normal' | 'verbose'` `object` - -This option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you want some bundle information, but not all of it. - -To show only errors in your bundle: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - stats: 'errors-only' - } -}; -``` - -For more information, see the [__stats documentation__](/configuration/stats/). - -T> This option has no effect when used with `quiet` or `noInfo`. - - -## `devServer.stdin` - CLI only - -`boolean` - -This option closes the server when stdin ends. - -```bash -webpack-dev-server --stdin -``` - - -## `devServer.useLocalIp` - -`boolean` - -This option lets the browser open with your local IP. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - useLocalIp: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --useLocalIp -``` - - -## `devServer.watchContentBase` - -`boolean` - -Tell dev-server to watch the files served by the [`devServer.contentBase`](#devserver-contentbase) option. It is disabled by default. When enabled, file changes will trigger a full page reload. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - watchContentBase: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --watch-content-base -``` - - -## `devServer.watchOptions` 🔑 - -`object` - -Control options related to watching the files. - -webpack uses the file system to get notified of file changes. In some cases this does not work. For example, when using Network File System (NFS). [Vagrant](https://www.vagrantup.com/) also has a lot of problems with this. In these cases, use polling: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - watchOptions: { - poll: true - } - } -}; -``` - -If this is too heavy on the file system, you can change this to an integer to set the interval in milliseconds. - -See [WatchOptions](/configuration/watch/) for more options. - - -# Devtool - -This option controls if and how source maps are generated. - -Use the [`SourceMapDevToolPlugin`](/plugins/source-map-dev-tool-plugin) for a more fine grained configuration. See the [`source-map-loader`](/loaders/source-map-loader) to deal with existing source maps. - - -## `devtool` - -`string` `false` - -Choose a style of [source mapping](http://blog.teamtreehouse.com/introduction-source-maps) to enhance the debugging process. These values can affect build and rebuild speed dramatically. - -T> The webpack repository contains an [example showing the effect of all `devtool` variants](https://github.com/webpack/webpack/tree/master/examples/source-map). Those examples will likely help you to understand the differences. - -T> Instead of using the `devtool` option you can also use `SourceMapDevToolPlugin`/`EvalSourceMapDevToolPlugin` directly as it has more options. Never use both the `devtool` option and plugin together. The `devtool` option adds the plugin internally so you would end up with the plugin applied twice. - -devtool | build | rebuild | production | quality ------------------------------- | ----- | ------- | ---------- | ----------------------------- -(none) | +++ | +++ | yes | bundled code -eval | +++ | +++ | no | generated code -cheap-eval-source-map | + | ++ | no | transformed code (lines only) -cheap-module-eval-source-map | o | ++ | no | original source (lines only) -eval-source-map | -- | + | no | original source -cheap-source-map | + | o | yes | transformed code (lines only) -cheap-module-source-map | o | - | yes | original source (lines only) -inline-cheap-source-map | + | o | no | transformed code (lines only) -inline-cheap-module-source-map | o | - | no | original source (lines only) -source-map | -- | -- | yes | original source -inline-source-map | -- | -- | no | original source -hidden-source-map | -- | -- | yes | original source -nosources-source-map | -- | -- | yes | without source content - -T> `+++` super fast, `++` fast, `+` pretty fast, `o` medium, `-` pretty slow, `--` slow - -Some of these values are suited for development and some for production. For development you typically want fast Source Maps at the cost of bundle size, but for production you want separate Source Maps that are accurate and support minimizing. - -W> There are some issues with Source Maps in Chrome. [We need your help!](https://github.com/webpack/webpack/issues/3165). - -T> See [`output.sourceMapFilename`](/configuration/output#output-sourcemapfilename) to customize the filenames of generated Source Maps. - - -### Qualities - -`bundled code` - You see all generated code as a big blob of code. You don't see modules separated from each other. - -`generated code` - You see each module separated from each other, annotated with module names. You see the code generated by webpack. Example: Instead of `import {test} from "module"; test();` you see something like `var module__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); module__WEBPACK_IMPORTED_MODULE_1__.a();`. - -`transformed code` - You see each module separated from each other, annotated with module names. You see the code before webpack transforms it, but after Loaders transpile it. Example: Instead of `import {test} from "module"; class A extends test {}` you see something like `import {test} from "module"; var A = function(_test) { ... }(test);` - -`original source` - You see each module separated from each other, annotated with module names. You see the code before transpilation, as you authored it. This depends on Loader support. - -`without source content` - Contents for the sources are not included in the Source Maps. Browsers usually try to load the source from the webserver or filesystem. You have to make sure to set [`output.devtoolModuleFilenameTemplate`](/configuration/output/#output-devtoolmodulefilenametemplate) correctly to match source urls. - -`(lines only)` - Source Maps are simplified to a single mapping per line. This usually means a single mapping per statement (assuming you author is this way). This prevents you from debugging execution on statement level and from settings breakpoints on columns of a line. Combining with minimizing is not possible as minimizers usually only emit a single line. - - -### Development - -The following options are ideal for development: - -`eval` - Each module is executed with `eval()` and `//@ sourceURL`. This is pretty fast. The main disadvantage is that it doesn't display line numbers correctly since it gets mapped to transpiled code instead of the original code (No Source Maps from Loaders). - -`eval-source-map` - Each module is executed with `eval()` and a SourceMap is added as a DataUrl to the `eval()`. Initially it is slow, but it provides fast rebuild speed and yields real files. Line numbers are correctly mapped since it gets mapped to the original code. It yields the best quality SourceMaps for development. - -`cheap-eval-source-map` - Similar to `eval-source-map`, each module is executed with `eval()`. It is "cheap" because it doesn't have column mappings, it only maps line numbers. It ignores SourceMaps from Loaders and only display transpiled code similar to the `eval` devtool. - -`cheap-module-eval-source-map` - Similar to `cheap-eval-source-map`, however, in this case Source Maps from Loaders are processed for better results. However Loader Source Maps are simplified to a single mapping per line. - -### Special cases - -The following options are not ideal for development nor production. They are needed for some special cases, i. e. for some 3rd party tools. - -`inline-source-map` - A SourceMap is added as a DataUrl to the bundle. - -`cheap-source-map` - A SourceMap without column-mappings ignoring loader Source Maps. - -`inline-cheap-source-map` - Similar to `cheap-source-map` but SourceMap is added as a DataUrl to the bundle. - -`cheap-module-source-map` - A SourceMap without column-mappings that simplifies loader Source Maps to a single mapping per line. - -`inline-cheap-module-source-map` - Similar to `cheap-module-source-map` but SourceMap is added as a DataUrl to the bundle. - - -### Production - -These options are typically used in production: - -`(none)` (Omit the `devtool` option) - No SourceMap is emitted. This is a good option to start with. - -`source-map` - A full SourceMap is emitted as a separate file. It adds a reference comment to the bundle so development tools know where to find it. - -W> You should configure your server to disallow access to the Source Map file for normal users! - -`hidden-source-map` - Same as `source-map`, but doesn't add a reference comment to the bundle. Useful if you only want SourceMaps to map error stack traces from error reports, but don't want to expose your SourceMap for the browser development tools. - -W> You should not deploy the Source Map file to the webserver. Instead only use it for error report tooling. - -`nosources-source-map` - A SourceMap is created without the `sourcesContent` in it. It can be used to map stack traces on the client without exposing all of the source code. You can deploy the Source Map file to the webserver. - -W> It still exposes filenames and structure for decompiling, but it doesn't expose the original code. - -T> When using the `terser-webpack-plugin` you must provide the `sourceMap: true` option to enable SourceMap support. - - -# Target - -webpack can compile for multiple environments or _targets_. To understand what a `target` is in detail, read through [the targets concept page](/concepts/targets/). - -## `target` - -`string | function (compiler)` - -Instructs webpack to target a specific environment. - - -### `string` - -The following string values are supported via [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js): - -Option | Description ---------------------- | ----------------------- -`async-node` | Compile for usage in a Node.js-like environment (uses `fs` and `vm` to load chunks asynchronously) -`electron-main` | Compile for [Electron](https://electronjs.org/) for main process. -`electron-renderer` | Compile for [Electron](https://electronjs.org/) for renderer process, providing a target using `JsonpTemplatePlugin`, `FunctionModulePlugin` for browser environments and `NodeTargetPlugin` and `ExternalsPlugin` for CommonJS and Electron built-in modules. -`node` | Compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks) -`node-webkit` | Compile for usage in WebKit and uses JSONP for chunk loading. Allows importing of built-in Node.js modules and [`nw.gui`](http://docs.nwjs.io/en/latest/) (experimental) -`web` | Compile for usage in a browser-like environment __(default)__ -`webworker` | Compile as WebWorker - -For example, when the `target` is set to `"electron-main"`, webpack includes multiple electron specific variables. For more information on which templates and externals are used, you can refer to webpack's [source code](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js#L148-L183). - - -### `function` - -If a function is passed, then it will be called with the compiler as a parameter. Set it to a function if none of the predefined targets from the list above meet your needs. - -For example, if you don't want any of the plugins they applied: - -```js -const options = { - target: () => undefined -}; -``` - -Or you can apply specific plugins you want: - -```js -const webpack = require('webpack'); - -const options = { - target: (compiler) => { - compiler.apply( - new webpack.JsonpTemplatePlugin(options.output), - new webpack.LoaderTargetPlugin('web') - ); - } -}; -``` - - -# Watch and WatchOptions - -webpack can watch files and recompile whenever they change. This page explains how to enable this and a couple of tweaks you can make if watching does not work properly for you. - - -## `watch` - -`boolean` - -Turn on watch mode. This means that after the initial build, webpack will continue to watch for changes in any of the resolved files. Watch mode is turned off by default: - -```js -module.exports = { - //... - watch: false -}; -``` - -T> In webpack-dev-server and webpack-dev-middleware watch mode is enabled by default. - - -## `watchOptions` - -`object` - -A set of options used to customize watch mode: - -```js -module.exports = { - //... - watchOptions: { - aggregateTimeout: 300, - poll: 1000 - } -}; -``` - - -## `watchOptions.aggregateTimeout` - -`number` - -Add a delay before rebuilding once the first file changed. This allows webpack to aggregate any other changes made during this time period into one rebuild. Pass a value in milliseconds: - -```js -module.exports = { - //... - watchOptions: { - aggregateTimeout: 300 // The default - } -}; -``` - - -## `watchOptions.ignored` - -For some systems, watching many file systems can result in a lot of CPU or memory usage. It is possible to exclude a huge folder like `node_modules`: - -```js -module.exports = { - //... - watchOptions: { - ignored: /node_modules/ - } -}; -``` - -It is also possible to have and use multiple [anymatch](https://github.com/micromatch/anymatch) patterns: - -```js -module.exports = { - //... - watchOptions: { - ignored: ['files/**/*.js', 'node_modules'] - } -}; -``` - -T> If you use `require.context`, webpack will watch your entire directory. You will need to ignore files and/or directories so that unwanted changes will not trigger a rebuild. - - -## `watchOptions.poll` - -`boolean` `number` - -Turn on [polling](https://whatis.techtarget.com/definition/polling) by passing `true`, or specifying a poll interval in milliseconds: - -```js -module.exports = { - //... - watchOptions: { - poll: 1000 // Check for changes every second - } -}; -``` - -T> If watching does not work for you, try out this option. Watching does not work with NFS and machines in VirtualBox. - - -## `info-verbosity` - -`string`: `none` `info` `verbose` - -Controls verbosity of the lifecycle messaging, e.g. the `Started watching files...` log. Setting `info-verbosity` to `verbose` will also message to console at the beginning and the end of incremental build. `info-verbosity` is set to `info` by default. - -```bash -webpack --watch --info-verbosity verbose -``` - - -## Troubleshooting - -If you are experiencing any issues, please see the following notes. There are a variety of reasons why webpack might miss a file change. - -### Changes Seen But Not Processed - -Verify that webpack is not being notified of changes by running webpack with the --progress flag. If progress shows on save but no files are outputted, it is likely a configuration issue, not a file watching issue. - -```bash -webpack --watch --progress -``` - -### Not Enough Watchers - -Verify that you have enough available watchers in your system. If this value is too low, the file watcher in Webpack won't recognize the changes: - -```bash -cat /proc/sys/fs/inotify/max_user_watches -``` - -Arch users, add `fs.inotify.max_user_watches=524288` to `/etc/sysctl.d/99-sysctl.conf` and then execute `sysctl --system`. Ubuntu users (and possibly others), execute: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`. - -### macOS fsevents Bug - -On macOS, folders can get corrupted in certain scenarios. See [this article](https://github.com/livereload/livereload-site/blob/master/livereload.com/_articles/troubleshooting/os-x-fsevents-bug-may-prevent-monitoring-of-certain-folders.md). - -### Windows Paths - -Because webpack expects absolute paths for many config options such as `__dirname + "/app/folder"` the Windows `\` path separator can break some functionality. - -Use the correct separators. I.e. `path.resolve(__dirname, "app/folder")` or `path.join(__dirname, "app", "folder")`. - -### Vim - -On some machines Vim is preconfigured with the [backupcopy option](http://vimdoc.sourceforge.net/htmldoc/options.html#'backupcopy') set to `auto`. This could potentially cause problems with the system's file watching mechanism. Switching this option to `yes` will make sure a copy of the file is made and the original one overwritten on save. - -`:set backupcopy=yes` - -### Saving in WebStorm - -When using the JetBrains WebStorm IDE, you may find that saving changed files does not trigger the watcher as you might expect. Try disabling the `safe write` option in the settings, which determines whether files are saved to a temporary location first before the originals are overwritten: uncheck `File > Settings... > System Settings > Use "safe write" (save changes to a temporary file first)`. - - -# Externals - -The `externals` configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment. This feature is typically most useful to __library developers__, however there are a variety of applications for it. - -T> __consumer__ here is any end user application that includes the library that you have bundled using webpack. - - -## `externals` - -`string` `object` `function` `regex` - -__Prevent bundling__ of certain `import`ed packages and instead retrieve these _external dependencies_ at runtime. - -For example, to include [jQuery](https://jquery.com/) from a CDN instead of bundling it: - -__index.html__ - -``` html -<script - src="https://code.jquery.com/jquery-3.1.0.js" - integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" - crossorigin="anonymous"> -</script> -``` - -__webpack.config.js__ - -```javascript -module.exports = { - //... - externals: { - jquery: 'jQuery' - } -}; -``` - -This leaves any dependent modules unchanged, i.e. the code shown below will still work: - -```javascript -import $ from 'jquery'; - -$('.my-element').animate(/* ... */); -``` - -The bundle with external dependencies can be used in various module contexts, such as [CommonJS, AMD, global and ES2015 modules](/concepts/modules). The external library may be available in any of these forms: - -- __root__: The library should be available as a global variable (e.g. via a script tag). -- __commonjs__: The library should be available as a CommonJS module. -- __commonjs2__: Similar to the above but where the export is `module.exports.default`. -- __amd__: Similar to `commonjs` but using AMD module system. - -The following syntaxes are accepted... - - -### string - -See the example above. The property name `jquery` indicates that the module `jquery` in `import $ from 'jquery'` should be excluded. In order to replace this module, the value `jQuery` will be used to retrieve a global `jQuery` variable. In other words, when a string is provided it will be treated as `root` (defined above and below). - - -### array - -```javascript -module.exports = { - //... - externals: { - subtract: ['./math', 'subtract'] - } -}; -``` - -`subtract: ['./math', 'subtract']` converts to a parent child construct, where `./math` is the parent module and your bundle only requires the subset under `subtract` variable. - - -### object - -W> An object with `{ root, amd, commonjs, ... }` is only allowed for [`libraryTarget: 'umd'`](/configuration/output/#output-librarytarget). It's not allowed for other library targets. - -```javascript -module.exports = { - //... - externals : { - react: 'react' - }, - - // or - - externals : { - lodash : { - commonjs: 'lodash', - amd: 'lodash', - root: '_' // indicates global variable - } - }, - - // or - - externals : { - subtract : { - root: ['math', 'subtract'] - } - } -}; -``` - -This syntax is used to describe all the possible ways that an external library can be available. `lodash` here is available as `lodash` under AMD and CommonJS module systems but available as `_` in a global variable form. `subtract` here is available via the property `subtract` under the global `math` object (e.g. `window['math']['subtract']`). - - -### function - -It might be useful to define your own function to control the behavior of what you want to externalize from webpack. [webpack-node-externals](https://www.npmjs.com/package/webpack-node-externals), for example, excludes all modules from the `node_modules` directory and provides some options to, for example, whitelist packages. - -It basically comes down to this: - -```javascript -module.exports = { - //... - externals: [ - function(context, request, callback) { - if (/^yourregex$/.test(request)){ - return callback(null, 'commonjs ' + request); - } - callback(); - } - ] -}; -``` - -The `'commonjs ' + request` defines the type of module that needs to be externalized. - - -### regex - -Every dependency that matches the given regular expression will be excluded from the output bundles. - -```javascript -module.exports = { - //... - externals: /^(jquery|\$)$/i -}; -``` - -In this case any dependency named `jQuery`, capitalized or not, or `$` would be externalized. - -### Combining syntaxes - -Sometimes you may want to use a combination of the above syntaxes. This can be done in the following manner: - -```javascript -module.exports = { - //... - externals: [ - { - // String - react: 'react', - // Object - lodash : { - commonjs: 'lodash', - amd: 'lodash', - root: '_' // indicates global variable - }, - // Array - subtract: ['./math', 'subtract'] - }, - // Function - function(context, request, callback) { - if (/^yourregex$/.test(request)){ - return callback(null, 'commonjs ' + request); - } - callback(); - }, - // Regex - /^(jquery|\$)$/i - ] -}; -``` - -For more information on how to use this configuration, please refer to the article on [how to author a library](/guides/author-libraries). - - -# Node - -These options configure whether to polyfill or mock certain [Node.js globals](https://nodejs.org/docs/latest/api/globals.html) and modules. This allows code originally written for the Node.js environment to run in other environments like the browser. - -This feature is provided by webpack's internal [`NodeStuffPlugin`](https://github.com/webpack/webpack/blob/master/lib/NodeStuffPlugin.js) plugin. If the target is "web" (default) or "webworker", the [`NodeSourcePlugin`](https://github.com/webpack/webpack/blob/master/lib/node/NodeSourcePlugin.js) plugin is also activated. - - -## `node` - -`object` - -This is an object where each property is the name of a Node global or module and each value may be one of the following... - -- `true`: Provide a polyfill. -- `"mock"`: Provide a mock that implements the expected interface but has little or no functionality. -- `"empty"`: Provide an empty object. -- `false`: Provide nothing. Code that expects this object may crash with a `ReferenceError`. Code that attempts to import the module using `require('modulename')` may trigger a `Cannot find module "modulename"` error. - -W> Not every Node global supports all four options. The compiler will throw an error for property-value combinations that aren't supported (e.g. `process: 'empty'`). See the sections below for more details. - -These are the defaults: - -```js -module.exports = { - //... - node: { - console: false, - global: true, - process: true, - __filename: 'mock', - __dirname: 'mock', - Buffer: true, - setImmediate: true - - // See "Other node core libraries" for additional options. - } -}; -``` - -Since webpack 3.0.0, the `node` option may be set to `false` to completely turn off the `NodeStuffPlugin` and `NodeSourcePlugin` plugins. - - -## `node.console` - -`boolean | "mock"` - -Default: `false` - -The browser provides a `console` object with a very similar interface to the Node.js `console`, so a polyfill is generally not needed. - - -## `node.process` - -`boolean | "mock"` - -Default: `true` - - -## `node.global` - -`boolean` - -Default: `true` - -See [the source](https://github.com/webpack/webpack/blob/master/buildin/global.js) for the exact behavior of this object. - - -## `node.__filename` - -`boolean | "mock"` - -Default: `"mock"` - -Options: - -- `true`: The filename of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). -- `false`: The regular Node.js `__filename` behavior. The filename of the __output__ file when run in a Node.js environment. -- `"mock"`: The fixed value `"index.js"`. - - -## `node.__dirname` - -`boolean | "mock"` - -Default: `"mock"` - -Options: - -- `true`: The dirname of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). -- `false`: The regular Node.js `__dirname` behavior. The dirname of the __output__ file when run in a Node.js environment. -- `"mock"`: The fixed value `"/"`. - - -## `node.Buffer` - -`boolean | "mock"` - -Default: `true` - - -## `node.setImmediate` - -`boolean | "mock" | "empty"` - -Default: `true` - - -## Other node core libraries - -`boolean | "mock" | "empty"` - -W> This option is only activated (via `NodeSourcePlugin`) when the target is unspecified, "web" or "webworker". - -Polyfills for Node.js core libraries from [`node-libs-browser`](https://github.com/webpack/node-libs-browser) are used if available, when the `NodeSourcePlugin` plugin is enabled. See the list of [Node.js core libraries and their polyfills](https://github.com/webpack/node-libs-browser#readme). - -By default, webpack will polyfill each library if there is a known polyfill or do nothing if there is not one. In the latter case, webpack will behave as if the module name was configured with the `false` value. - -T> To import a built-in module, use [`__non_webpack_require__`](/api/module-variables/#__non_webpack_require__-webpack-specific-), i.e. `__non_webpack_require__('modulename')` instead of `require('modulename')`. - -Example: - -```js -module.exports = { - //... - node: { - dns: 'mock', - fs: 'empty', - path: true, - url: false - } -}; -``` - - -# Performance - -These options allows you to control how webpack notifies you of assets and entry points that exceed a specific file limit. -This feature was inspired by the idea of [webpack Performance Budgets](https://github.com/webpack/webpack/issues/3216). - -## `performance` - -`object` - -Configure how performance hints are shown. For example if you have an asset that is over 250kb, webpack will emit a warning notifying you of this. - - -## `performance.hints` - -`false | "error" | "warning"` - -Turns hints on/off. In addition, tells webpack to throw either an error or a warning when hints are found. This property is set to `"warning"` by default. - -Given an asset is created that is over 250kb: - -```js -module.exports = { - //... - performance: { - hints: false - } -}; -``` - -No hint warnings or errors are shown. - -```js -module.exports = { - //... - performance: { - hints: 'warning' - } -}; -``` - -A warning will be displayed notifying you of a large asset. We recommend something like this for development environments. - -```js -module.exports = { - //... - performance: { - hints: 'error' - } -}; -``` - -An error will be displayed notifying you of a large asset. We recommend using `hints: "error"` during production builds to help prevent deploying production bundles that are too large, impacting webpage performance. - -## `performance.maxEntrypointSize` - -`int` - -An entry point represents all assets that would be utilized during initial load time for a specific entry. This option controls when webpack should emit performance hints based on the maximum entry point size. The default value is `250000` (bytes). - -```js -module.exports = { - //... - performance: { - maxEntrypointSize: 400000 - } -}; -``` - -## `performance.maxAssetSize` - -`int` - -An asset is any emitted file from webpack. This option controls when webpack emits a performance hint based on individual asset size. The default value is `250000` (bytes). - - -```js -module.exports = { - //... - performance: { - maxAssetSize: 100000 - } -}; -``` - -## `performance.assetFilter` - -`Function` - -This property allows webpack to control what files are used to calculate performance hints. The default function is seen below: - -```js -function assetFilter(assetFilename) { - return !(/\.map$/.test(assetFilename)); -} -``` - -You can override this property by passing your own function in: - -```js -module.exports = { - //... - performance: { - assetFilter: function(assetFilename) { - return assetFilename.endsWith('.js'); - } - } -}; -``` - -The example above will only give you performance hints based on `.js` files. - - -# Stats - -The `stats` option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you don't want to use `quiet` or `noInfo` because you want some bundle information, but not all of it. - -T> For webpack-dev-server, this property needs to be in the `devServer` object. - -W> This option does not have any effect when using the Node.js API. - -## `stats` - -`object` `string` - -There are some presets available to use as a shortcut. Use them like this: - -```js -module.exports = { - //... - stats: 'errors-only' -}; -``` - -| Preset | Alternative | Description | -|--------|-------------|-------------| -| `"errors-only"` | _none_ | Only output when errors happen | -| `"minimal"` | _none_ | Only output when errors or new compilation happen | -| `"none"` | `false` | Output nothing | -| `"normal"` | `true` | Standard output | -| `"verbose"` | _none_ | Output everything | - -For more granular control, it is possible to specify exactly what information you want. Please note that all of the options in this object are optional. - -<!-- eslint-skip --> - -```js -module.exports = { - //... - stats: { - // fallback value for stats options when an option is not defined (has precedence over local webpack defaults) - all: undefined, - - // Add asset Information - assets: true, - - // Sort assets by a field - // You can reverse the sort with `!field`. - // Some possible values: 'id' (default), 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - assetsSort: "field", - - // Add build date and time information - builtAt: true, - - // Add information about cached (not built) modules - cached: true, - - // Show cached assets (setting this to `false` only shows emitted files) - cachedAssets: true, - - // Add children information - children: true, - - // Add chunk information (setting this to `false` allows for a less verbose output) - chunks: true, - - // Add namedChunkGroups information - chunkGroups: true, - - // Add built modules information to chunk information - chunkModules: true, - - // Add the origins of chunks and chunk merging info - chunkOrigins: true, - - // Sort the chunks by a field - // You can reverse the sort with `!field`. Default is `id`. - // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - chunksSort: "field", - - // Context directory for request shortening - context: "../src/", - - // `webpack --colors` equivalent - colors: false, - - // Display the distance from the entry point for each module - depth: false, - - // Display the entry points with the corresponding bundles - entrypoints: false, - - // Add --env information - env: false, - - // Add errors - errors: true, - - // Add details to errors (like resolving log) - errorDetails: true, - - // Exclude assets from being displayed in stats - // This can be done with a String, a RegExp, a Function getting the assets name - // and returning a boolean or an Array of the above. - excludeAssets: "filter" | /filter/ | (assetName) => true | false | - ["filter"] | [/filter/] | [(assetName) => true|false], - - // Exclude modules from being displayed in stats - // This can be done with a String, a RegExp, a Function getting the modules source - // and returning a boolean or an Array of the above. - excludeModules: "filter" | /filter/ | (moduleSource) => true | false | - ["filter"] | [/filter/] | [(moduleSource) => true|false], - - // See excludeModules - exclude: "filter" | /filter/ | (moduleSource) => true | false | - ["filter"] | [/filter/] | [(moduleSource) => true|false], - - // Add the hash of the compilation - hash: true, - - // Set the maximum number of modules to be shown - maxModules: 15, - - // Add built modules information - modules: true, - - // Sort the modules by a field - // You can reverse the sort with `!field`. Default is `id`. - // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - modulesSort: "field", - - // Show dependencies and origin of warnings/errors (since webpack 2.5.0) - moduleTrace: true, - - // Show performance hint when file size exceeds `performance.maxAssetSize` - performance: true, - - // Show the exports of the modules - providedExports: false, - - // Add public path information - publicPath: true, - - // Add information about the reasons why modules are included - reasons: true, - - // Add the source code of modules - source: false, - - // Add timing information - timings: true, - - // Show which exports of a module are used - usedExports: false, - - // Add webpack version information - version: true, - - // Add warnings - warnings: true, - - // Filter warnings to be shown (since webpack 2.4.0), - // can be a String, Regexp, a function getting the warning and returning a boolean - // or an Array of a combination of the above. First match wins. - warningsFilter: "filter" | /filter/ | ["filter", /filter/] | (warning) => true|false - } -} -``` - -If you want to use one of the pre-defined behaviours e.g. `'minimal'` but still override one or more of the rules, see [the source code](https://github.com/webpack/webpack/blob/master/lib/Stats.js#L1394-L1401). You would want to copy the configuration options from `case 'minimal': ...` and add your additional rules while providing an object to `stats`. - -__webpack.config.js__ - -```javascript -module.exports = { - //.. - stats: { - // copied from `'minimal'` - all: false, - modules: true, - maxModules: 0, - errors: true, - warnings: true, - // our additional options - moduleTrace: true, - errorDetails: true - } -}; -``` - -### Sorting fields - -For `assetsSort`, `chunksSort` and `moduleSort` there are several possible fields that you can sort items by: - -- `id` is the item's id; -- `name` - a item's name that was assigned to it upon importing; -- `size` - a size of item in bytes; -- `chunks` - what chunks the item originates from (for example, if there are multiple subchunks for one chunk - the subchunks will be grouped together according to their main chunk); -- `errors` - amount of errors in items; -- `warnings` - amount of warnings in items; -- `failed` - whether the item has failed compilation; -- `cacheable` - whether the item is cacheable; -- `built` - whether the asset has been built; -- `prefetched` - whether the asset will be prefetched; -- `optional` - whether the asset is optional; -- `identifier` - identifier of the item; -- `index` - item's processing index; -- `index2` -- `profile` -- `issuer` - an identifier of the issuer; -- `issuerId` - an id of the issuer; -- `issuerName` - a name of the issuer; -- `issuerPath` - a full issuer object. There's no real need to sort by this field; - - -# Other Options - - -These are the remaining configuration options supported by webpack. - -W> Help Wanted: This page is still a work in progress. If you are familiar with any of the options for which the description or examples are incomplete, please create an issue and submit a PR at the [docs repo](https://github.com/webpack/webpack.js.org)! - - -## `amd` - -`object` - -Set the value of `require.amd` or `define.amd`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - amd: { - jQuery: true - } -}; -``` - -Certain popular modules written for AMD, most notably jQuery versions 1.7.0 to 1.9.1, will only register as an AMD module if the loader indicates it has taken [special allowances](https://github.com/amdjs/amdjs-api/wiki/jQuery-and-AMD) for multiple versions being included on a page. - -The allowances were the ability to restrict registrations to a specific version or to support different sandboxes with different defined modules. - -This option allows you to set the key your module looks for to a truthy value. -As it happens, the AMD support in webpack ignores the defined name anyways. - - -## `bail` - -`boolean` - -Fail out on the first error instead of tolerating it. By default webpack will log these errors in red in the terminal, as well as the browser console when using HMR, but continue bundling. To enable it: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - bail: true -}; -``` - -This will force webpack to exit its bundling process. - - -## `cache` - -`boolean` `object` - -Cache the generated webpack modules and chunks to improve build speed. Caching is enabled by default while in watch mode. To disable caching simply pass: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - cache: false -}; -``` - -If an object is passed, webpack will use this object for caching. Keeping a reference to this object will allow one to share the same cache between compiler calls: - -__webpack.config.js__ - -```javascript -let SharedCache = {}; - -module.exports = { - //... - cache: SharedCache -}; -``` - -W> Don't share the cache between calls with different options. - -?> Elaborate on the warning and example - calls with different configuration options? - - -## `loader` - -`object` - -Expose custom values into the loader context. - -?> Add an example... - - -## `parallelism` - -`number` - -Limit the number of parallel processed modules. Can be used to fine tune performance or to get more reliable profiling results. - - -## `profile` - -`boolean` - -Capture a "profile" of the application, including statistics and hints, which can then be dissected using the [Analyze](https://webpack.github.io/analyse/) tool. - -T> Use the [StatsPlugin](https://www.npmjs.com/package/stats-webpack-plugin) for more control over the generated profile. - -T> Combine with `parallelism: 1` for better results. - - -## `recordsPath` - -`string` - -Use this option to generate a JSON file containing webpack "records" -- pieces of data used to store module identifiers across multiple builds. You can use this file to track how modules change between builds. To generate one, simply specify a location: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - recordsPath: path.join(__dirname, 'records.json') -}; -``` - -Records are particularly useful if you have a complex setup that leverages [Code Splitting](/guides/code-splitting). The data can be used to ensure the split bundles are achieving the [caching](/guides/caching) behavior you need. - -T> Note that although this file is generated by the compiler, you may still want to track it in source control to keep a history of how it has changed over time. - -W> Setting `recordsPath` will essentially set `recordsInputPath` and `recordsOutputPath` to the same location. This is usually all that's necessary unless you decide to change the name of the file containing the records. See below for an example. - - -## `recordsInputPath` - -`string` - -Specify the file from which to read the last set of records. This can be used to rename a records file. See the example below. - - -## `recordsOutputPath` - -`string` - -Specify where the records should be written. The following example shows how you might use this option in combination with `recordsInputPath` to rename a records file: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - recordsInputPath: path.join(__dirname, 'records.json'), - recordsOutputPath: path.join(__dirname, 'newRecords.json') -}; -``` - - -## `name` - -`string` - -Name of the configuration. Used when loading multiple configurations. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - name: 'admin-app' -}; -``` diff --git a/src/content/contribute/_contribute_all.md b/src/content/contribute/_contribute_all.md deleted file mode 100644 index beab316a12a7..000000000000 --- a/src/content/contribute/_contribute_all.md +++ /dev/null @@ -1,979 +0,0 @@ - - -# Contribute - -The people who contribute to webpack do so for the love of open source, our users and ecosystem, and most importantly, pushing the web forward together. Because of our [Open Collective](https://opencollective.com/webpack) model for funding and transparency, we are able to funnel support and funds through contributors, dependent projects, and the contributor and core teams. To make a donation, simply click the button below... - -<div align="center"> - <a href="https://opencollective.com/webpack/donate" target="_blank"> - <img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" width=300 /> - </a> -</div> - -But what is the return on the investment? - - -## Developers - -The biggest core feature we'd like to provide is enjoyable development experience. Developers like you can help by contributing to rich and vibrant documentation, issuing pull requests to help us cover niche use cases, and to help sustain what you love about webpack. - -### How Can I Help? - -Anybody can help by doing any of the following: - -- Ask your employer to use webpack in projects. -- Help us write and maintain the content on this site (see the [writer's guide](/writers-guide)). -- Contribute to the [core repository](https://github.com/webpack/webpack). -- Become a backer or sponsor on [open collective](https://opencollective.com/webpack#support). - -### Encouraging Employers - -You can ask your employer to improve your workflow by leveraging webpack: an all-in-one tool for fonts, images and image optimization, and json. Explain to them how webpack will attempt to bundle your code and assets the best it can for the smallest file size, leading to speedier sites and applications. - -### Your Contributions - -Contributing to webpack is not contributing to an exclusive club. You as a developer are contributing to the overall health of downstream projects. Hundreds, if not thousands, of projects depend on webpack and contributing will make the ecosystem better for all users. - -The remainder of this section of the site is dedicated to developers such as yourself who would like to become a part of our ever-growing community: - -- [Writing a Loader](./writing-a-loader) -- [Writing a Plugin](./writing-a-plugin) -- [Plugin Patterns](./plugin-patterns) -- [Release Process](./release-process) - - -## Executives - -CTO's, VPs, and owners can help too! - -<!-- add slides here regarding monetary value/dev time/tooling --> - -webpack is an all-in-one tool for bundling your code. It can handle fonts, images, data and more with the help of community-driven plugins and loaders. Having all of your assets be handled by one tool is immensely helpful, as you or your team can spend less time making sure a machine with many moving parts is working correctly and more time building your product. - -### Sponsorship - -Aside from monetary assistance, companies can support webpack by: - -- Providing developers that are not actively working on a project. -- Contributing computing power for improved CI and regression testing. - -You can also encourage your developers to contribute to the ecosystem by open-sourcing webpack loaders, plugins and other utilities. And, as mentioned above, we would greatly appreciate any help increasing our CI/CD infrastructure. - -### Anyone Else - -To anyone else who is interested in helping our mission -- e.g. venture capitalists, government entities, digital agencies, etc. -- we would love for you to work with us, one of the top npm packages, to improve your product! Please don't hesitate to reach out with questions. - -<!-- add slides here --> - - -# Writer's Guide - -The following sections contain all you need to know about editing and formatting the content within this site. Make sure to do some research before starting your edits or additions. Sometimes the toughest part is finding where the content should live and determining whether or not it already exists. - - -## Process - -1. Check related issue if an article links to one. -2. Hit `edit` and expand on the structure. -3. PR changes. - - -## YAML Frontmatter - -Each article contains a small section at the top written in [YAML Frontmatter](https://jekyllrb.com/docs/frontmatter/): - -``` yaml ---- -title: My Article -group: My Sub-Section -sort: 3 -contributors: - - [github username] -related: - - title: Title of Related Article - url: [url of related article] ---- -``` - -Let's break these down: - -- `title`: The name of the article. -- `group`: The name of the sub-section -- `sort`: The order of the article within its section (or) sub-section if it is present. -- `contributors`: A list of GitHub usernames who have contributed to this article. -- `related`: Any related reading or useful examples. - -Note that `related` will generate a __Further Reading__ section at the bottom of the page and `contributors` will yield a __Contributors__ section below it. If you edit an article and would like recognition, don't hesitate to add your GitHub username to the `contributors` list. - - -## Article Structure - -1. Brief Introduction - a paragraph or two so you get the basic idea about the what and why. -2. Outline Remaining Content – how the content will be presented. -3. Main Content - tell what you promised to tell. -4. Conclusion - tell what you told and recap the main points. - - -## Typesetting - -- webpack should always be written in lower-case letters. Even at the beginning of a sentence. ([source](https://github.com/webpack/media#name)) -- loaders are enclosed in backticks and [kebab-cased](https://en.wikipedia.org/w/index.php?title=Kebab_case): `css-loader`, `ts-loader`, … -- plugins are enclosed in backticks and [camel-cased](https://en.wikipedia.org/wiki/Camel_case): `BannerPlugin`, `NpmInstallWebpackPlugin`, … -- Use "webpack 2" to refer to a specific webpack version (~~"webpack v2"~~) -- Use ES5; ES2015, ES2016, … to refer to the ECMAScript standards (~~ES6~~, ~~ES7~~) - - -## Formatting - -### Code - -__Syntax: \`\`\`javascript … \`\`\`__ - -```javascript -function foo () { - return 'bar'; -} - -foo(); -``` - -### Lists - -- Boo -- Foo -- Zoo - -Lists should be ordered alphabetically. - -### Tables - -Parameter | Explanation | Input Type | Default Value ------------ | ------------------------------------------------ | ---------- |-------------- ---debug | Switch loaders to debug mode | boolean | false ---devtool | Define source map type for the bundled resources | string | - ---progress | Print compilation progress in percentage | boolean | false - -Tables should also be ordered alphabetically. - -### Configuration Properties - -The [configuration](/configuration) properties should be ordered alphabetically as well: - -- `devServer.compress` -- `devServer.contentBase` -- `devServer.hot` - -### Quotes - -#### Blockquote - -__Syntax: \>__ - -> This is a blockquote. - -#### Tip - -__Syntax: T\>__ - -T> This is a tip. - -__Syntax: W\>__ - -W> This is a warning. - -__Syntax: ?\>__ - -?> This is a todo. - - -# Writing a Loader - -A loader is a node module that exports a function. This function is called when a resource should be transformed by this loader. The given function will have access to the [Loader API](/api/loaders/) using the `this` context provided to it. - - -## Setup - -Before we dig into the different types of loaders, their usage, and examples, let's take a look at the three ways you can develop and test a loader locally. - -To test a single loader, you can simply use `path` to `resolve` a local file within a rule object: - -__webpack.config.js__ - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - use: [ - { - loader: path.resolve('path/to/loader.js'), - options: {/* ... */} - } - ] - } - ] - } -}; -``` - -To test multiple, you can utilize the `resolveLoader.modules` configuration to update where webpack will search for loaders. For example, if you had a local `/loaders` directory in your project: - -__webpack.config.js__ - -```js -module.exports = { - //... - resolveLoader: { - modules: [ - 'node_modules', - path.resolve(__dirname, 'loaders') - ] - } -}; -``` - -Last but not least, if you've already created a separate repository and package for your loader, you could [`npm link`](https://docs.npmjs.com/cli/link) it to the project in which you'd like to test it out. - - -## Simple Usage - -When a single loader is applied to the resource, the loader is called with only one parameter -- a string containing the content of the resource file. - -Synchronous loaders can simply `return` a single value representing the transformed module. In more complex cases, the loader can return any number of values by using the `this.callback(err, values...)` function. Errors are either passed to the `this.callback` function or thrown in a sync loader. - -The loader is expected to give back one or two values. The first value is a resulting JavaScript code as string or buffer. The second optional value is a SourceMap as JavaScript object. - - -## Complex Usage - -When multiple loaders are chained, it is important to remember that they are executed in reverse order -- either right to left or bottom to top depending on array format. - -- The last loader, called first, will be passed the contents of the raw resource. -- The first loader, called last, is expected to return JavaScript and an optional source map. -- The loaders in between will be executed with the result(s) of the previous loader in the chain. - -So, in the following example, the `foo-loader` would be passed the raw resource and the `bar-loader` would receive the output of the `foo-loader` and return the final transformed module and a source map if necessary. - -__webpack.config.js__ - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js/, - use: [ - 'bar-loader', - 'foo-loader' - ] - } - ] - } -}; -``` - - -## Guidelines - -The following guidelines should be followed when writing a loader. They are ordered in terms of importance and some only apply in certain scenarios, read the detailed sections that follow for more information. - -- Keep them __simple__. -- Utilize __chaining__. -- Emit __modular__ output. -- Make sure they're __stateless__. -- Employ __loader utilities__. -- Mark __loader dependencies__. -- Resolve __module dependencies__. -- Extract __common code__. -- Avoid __absolute paths__. -- Use __peer dependencies__. - -### Simple - -Loaders should do only a single task. This not only makes the job of maintaining each loader easier, but also allows them to be chained for usage in more scenarios. - -### Chaining - -Take advantage of the fact that loaders can be chained together. Instead of writing a single loader that tackles five tasks, write five simpler loaders that divide this effort. Isolating them not only keeps each individual loader simple, but may allow for them to be used for something you hadn't thought of originally. - -Take the case of rendering a template file with data specified via loader options or query parameters. It could be written as a single loader that compiles the template from source, executes it and returns a module that exports a string containing the HTML code. However, in accordance with guidelines, a simple `apply-loader` exists that can be chained with other open source loaders: - -- `jade-loader`: Convert template to a module that exports a function. -- `apply-loader`: Executes the function with loader options and returns raw HTML. -- `html-loader`: Accepts HTML and outputs a valid JavaScript module. - -T> The fact that loaders can be chained also means they don't necessarily have to output JavaScript. As long as the next loader in the chain can handle its output, the loader can return any type of module. - -### Modular - -Keep the output modular. Loader generated modules should respect the same design principles as normal modules. - -### Stateless - -Make sure the loader does not retain state between module transformations. Each run should always be independent of other compiled modules as well as previous compilations of the same module. - -### Loader Utilities - -Take advantage of the [`loader-utils`](https://github.com/webpack/loader-utils) package. It provides a variety of useful tools but one of the most common is retrieving the options passed to the loader. Along with `loader-utils`, the [`schema-utils`](https://github.com/webpack-contrib/schema-utils) package should be used for consistent JSON Schema based validation of loader options. Here's a brief example that utilizes both: - -__loader.js__ - -```js -import { getOptions } from 'loader-utils'; -import validateOptions from 'schema-utils'; - -const schema = { - type: 'object', - properties: { - test: { - type: 'string' - } - } -}; - -export default function(source) { - const options = getOptions(this); - - validateOptions(schema, options, 'Example Loader'); - - // Apply some transformations to the source... - - return `export default ${ JSON.stringify(source) }`; -} -``` - -### Loader Dependencies - -If a loader uses external resources (i.e. by reading from filesystem), they __must__ indicate it. This information is used to invalidate cacheable loaders and recompile in watch mode. Here's a brief example of how to accomplish this using the `addDependency` method: - -__loader.js__ - -```js -import path from 'path'; - -export default function(source) { - var callback = this.async(); - var headerPath = path.resolve('header.js'); - - this.addDependency(headerPath); - - fs.readFile(headerPath, 'utf-8', function(err, header) { - if(err) return callback(err); - callback(null, header + '\n' + source); - }); -} -``` - -### Module Dependencies - -Depending on the type of module, there may be a different schema used to specify dependencies. In CSS for example, the `@import` and `url(...)` statements are used. These dependencies should be resolved by the module system. - -This can be done in one of two ways: - -- By transforming them to `require` statements. -- Using the `this.resolve` function to resolve the path. - -The `css-loader` is a good example of the first approach. It transforms dependencies to `require`s, by replacing `@import` statements with a `require` to the other stylesheet and `url(...)` with a `require` to the referenced file. - -In the case of the `less-loader`, it cannot transform each `@import` to a `require` because all `.less` files must be compiled in one pass for variables and mixin tracking. Therefore, the `less-loader` extends the less compiler with custom path resolving logic. It then takes advantage of the second approach, `this.resolve`, to resolve the dependency through webpack. - -T> If the language only accepts relative urls (e.g. `url(file)` always refers to `./file`), you can use the `~` convention to specify references to installed modules (e.g. those in `node_modules`). So, in the case of `url`, that would look something like `url('~some-library/image.jpg')`. - -### Common Code - -Avoid generating common code in every module the loader processes. Instead, create a runtime file in the loader and generate a `require` to that shared module. - -### Absolute Paths - -Don't insert absolute paths into the module code as they break hashing when the root for the project is moved. There's a [`stringifyRequest`](https://github.com/webpack/loader-utils#stringifyrequest) method in `loader-utils` which can be used to convert an absolute path to a relative one. - -### Peer Dependencies - -If the loader you're working on is a simple wrapper around another package, then you should include the package as a `peerDependency`. This approach allows the application's developer to specify the exact version in the `package.json` if desired. - -For instance, the `sass-loader` [specifies `node-sass`](https://github.com/webpack-contrib/sass-loader/blob/master/package.json) as peer dependency like so: - -```json -{ - "peerDependencies": { - "node-sass": "^4.0.0" - } -} -``` - - -## Testing - -So you've written a loader, followed the guidelines above, and have it set up to run locally. What's next? Let's go through a simple unit testing example to ensure our loader is working the way we expect. We'll be using the [Jest](https://facebook.github.io/jest/) framework to do this. We'll also install `babel-jest` and some presets that will allow us to use the `import` / `export` and `async` / `await`. Let's start by installing and saving these as a `devDependencies`: - -``` bash -npm install --save-dev jest babel-jest babel-preset-env -``` - -__.babelrc__ - -```json -{ - "presets": [[ - "env", - { - "targets": { - "node": "4" - } - } - ]] -} -``` - -Our loader will process `.txt` files and simply replace any instance of `[name]` with the `name` option given to the loader. Then it will output a valid JavaScript module containing the text as it's default export: - -__src/loader.js__ - -```js -import { getOptions } from 'loader-utils'; - -export default function loader(source) { - const options = getOptions(this); - - source = source.replace(/\[name\]/g, options.name); - - return `export default ${ JSON.stringify(source) }`; -} -``` - -We'll use this loader to process the following file: - -__test/example.txt__ - -``` text -Hey [name]! -``` - -Pay close attention to this next step as we'll be using the [Node.js API](/api/node) and [`memory-fs`](https://github.com/webpack/memory-fs) to execute webpack. This lets us avoid emitting `output` to disk and will give us access to the `stats` data which we can use to grab our transformed module: - -``` bash -npm install --save-dev webpack memory-fs -``` - -__test/compiler.js__ - -```js -import path from 'path'; -import webpack from 'webpack'; -import memoryfs from 'memory-fs'; - -export default (fixture, options = {}) => { - const compiler = webpack({ - context: __dirname, - entry: `./${fixture}`, - output: { - path: path.resolve(__dirname), - filename: 'bundle.js', - }, - module: { - rules: [{ - test: /\.txt$/, - use: { - loader: path.resolve(__dirname, '../src/loader.js'), - options: { - name: 'Alice' - } - } - }] - } - }); - - compiler.outputFileSystem = new memoryfs(); - - return new Promise((resolve, reject) => { - compiler.run((err, stats) => { - if (err || stats.hasErrors()) reject(err); - - resolve(stats); - }); - }); -}; -``` - -T> In this case, we've inlined our webpack configuration but you can also accept a configuration as a parameter to the exported function. This would allow you to test multiple setups using the same compiler module. - -And now, finally, we can write our test and add an npm script to run it: - -__test/loader.test.js__ - -```js -import compiler from './compiler.js'; - -test('Inserts name and outputs JavaScript', async () => { - const stats = await compiler('example.txt'); - const output = stats.toJson().modules[0].source; - - expect(output).toBe('export default "Hey Alice!\\n"'); -}); -``` - -__package.json__ - -```json -{ - "scripts": { - "test": "jest" - } -} -``` - -With everything in place, we can run it and see if our new loader passes the test: - -``` bash - PASS test/loader.test.js - ✓ Inserts name and outputs JavaScript (229ms) - -Test Suites: 1 passed, 1 total -Tests: 1 passed, 1 total -Snapshots: 0 total -Time: 1.853s, estimated 2s -Ran all test suites. -``` - -It worked! At this point you should be ready to start developing, testing, and deploying your own loaders. We hope that you'll share your creations with the rest of the community! - - -# Writing a Plugin - -Plugins expose the full potential of the webpack engine to third-party developers. Using staged build callbacks, developers can introduce their own behaviors into the webpack build process. Building plugins is a bit more advanced than building loaders, because you'll need to understand some of the webpack low-level internals to hook into them. Be prepared to read some source code! - -## Creating a Plugin - -A plugin for webpack consists of - -- A named JavaScript function. -- Defines `apply` method in its prototype. -- Specifies an [event hook](/api/compiler-hooks/) to tap into. -- Manipulates webpack internal instance specific data. -- Invokes webpack provided callback after functionality is complete. - -```javascript -// A JavaScript class. -class MyExampleWebpackPlugin { - // Define `apply` as its prototype method which is supplied with compiler as its argument - apply(compiler) { - // Specify the event hook to attach to - compiler.hooks.emit.tapAsync( - 'MyExampleWebpackPlugin', - (compilation, callback) => { - console.log('This is an example plugin!'); - console.log('Here’s the `compilation` object which represents a single build of assets:', compilation); - - // Manipulate the build using the plugin API provided by webpack - compilation.addModule(/* ... */); - - callback(); - } - ); - } -} -``` - -## Basic plugin architecture - -Plugins are instantiated objects with an `apply` method on their prototype. This `apply` method is called once by the webpack compiler while installing the plugin. The `apply` method is given a reference to the underlying webpack compiler, which grants access to compiler callbacks. A simple plugin is structured as follows: - -```javascript -class HelloWorldPlugin { - apply(compiler) { - compiler.hooks.done.tap('Hello World Plugin', ( - stats /* stats is passed as argument when done hook is tapped. */ - ) => { - console.log('Hello World!'); - }); - } -} - -module.exports = HelloWorldPlugin; -``` - -Then to use the plugin, include an instance in your webpack config `plugins` array: - -```javascript -// webpack.config.js -var HelloWorldPlugin = require('hello-world'); - -module.exports = { - // ... config settings here ... - plugins: [new HelloWorldPlugin({ options: true })] -}; -``` - -## Compiler and Compilation - -Among the two most important resources while developing plugins are the `compiler` and `compilation` objects. Understanding their roles is an important first step in extending the webpack engine. - -```javascript -class HelloCompilationPlugin { - apply(compiler) { - // Tap into compilation hook which gives compilation as argument to the callback function - compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => { - // Now we can tap into various hooks available through compilation - compilation.hooks.optimize.tap('HelloCompilationPlugin', () => { - console.log('Assets are being optimized.'); - }); - }); - } -} - -module.exports = HelloCompilationPlugin; -``` - -The list of hooks available on the `compiler`, `compilation`, and other important objects, see the [plugins API](/api/plugins/) docs. - -## Async event hooks - -Some plugin hooks are asynchronous. To tap into them, we can use `tap` method which will behave in synchronous manner or use one of `tapAsync` method or `tapPromise` method which are asynchronous methods. - -### tapAsync - -When we use `tapAsync` method to tap into plugins, we need to call the callback function which is supplied as the last argument to our function. - -```javascript -class HelloAsyncPlugin { - apply(compiler) { - compiler.hooks.emit.tapAsync('HelloAsyncPlugin', (compilation, callback) => { - // Do something async... - setTimeout(function() { - console.log('Done with async work...'); - callback(); - }, 1000); - }); - } -} - -module.exports = HelloAsyncPlugin; -``` - -#### tapPromise - -When we use `tapPromise` method to tap into plugins, we need to return a promise which resolves when our asynchronous task is completed. - -```javascript -class HelloAsyncPlugin { - apply(compiler) { - compiler.hooks.emit.tapPromise('HelloAsyncPlugin', compilation => { - // return a Promise that resolves when we are done... - return new Promise((resolve, reject) => { - setTimeout(function() { - console.log('Done with async work...'); - resolve(); - }, 1000); - }); - }); - } -} - -module.exports = HelloAsyncPlugin; -``` - -## Example - -Once we can latch onto the webpack compiler and each individual compilations, the possibilities become endless for what we can do with the engine itself. We can reformat existing files, create derivative files, or fabricate entirely new assets. - -Let's write a simple example plugin that generates a new build file called `filelist.md`; the contents of which will list all of the asset files in our build. This plugin might look something like this: - -```javascript -class FileListPlugin { - apply(compiler) { - // emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well - compiler.hooks.emit.tapAsync('FileListPlugin', (compilation, callback) => { - // Create a header string for the generated file: - var filelist = 'In this build:\n\n'; - - // Loop through all compiled assets, - // adding a new line item for each filename. - for (var filename in compilation.assets) { - filelist += '- ' + filename + '\n'; - } - - // Insert this list into the webpack build as a new file asset: - compilation.assets['filelist.md'] = { - source: function() { - return filelist; - }, - size: function() { - return filelist.length; - } - }; - - callback(); - }); - } -} - -module.exports = FileListPlugin; -``` - -## Different Plugin Shapes - -A plugin can be classified into types based on the event hooks it taps into. Every event hook is pre-defined as synchronous or asynchronous or waterfall or parallel hook and hook is called internally using call/callAsync method. The list of hooks that are supported or can be tapped into are generally specified in this.hooks property. - -For example:- - -```javascript -this.hooks = { - shouldEmit: new SyncBailHook(['compilation']) -}; -``` - -It represents that the only hook supported is `shouldEmit` which is a hook of `SyncBailHook` type and the only parameter which will be passed to any plugin that taps into `shouldEmit` hook is `compilation`. - -Various types of hooks supported are :- - -### Synchronous Hooks - -- __SyncHook__ - - - Defined as `new SyncHook([params])` - - Tapped into using `tap` method. - - Called using `call(...params)` method. - -- __Bail Hooks__ - - - Defined using `SyncBailHook[params]` - - Tapped into using `tap` method. - - Called using `call(...params)` method. - - In these type of hooks, each of the plugin callbacks will be invoked one after the other with the specific `args`. If any value is returned except undefined by any plugin, then that value is returned by hook and no further plugin callback is invoked. Many useful events like `optimizeChunks`, `optimizeChunkModules` are SyncBailHooks. - -- __Waterfall Hooks__ - - - Defined using `SyncWaterfallHook[params]` - - Tapped into using `tap` method. - - Called using `call( ... params)` method - - Here each of the plugins are called one after the other with the arguments from the return value of the previous plugin. The plugin must take the order of its execution into account. - It must accept arguments from the previous plugin that was executed. The value for the first plugin is `init`. Hence at least 1 param must be supplied for waterfall hooks. This pattern is used in the Tapable instances which are related to the webpack templates like `ModuleTemplate`, `ChunkTemplate` etc. - -### Asynchronous Hooks - -- __Async Series Hook__ - - - Defined using `AsyncSeriesHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - The plugin handler functions are called with all arguments and a callback function with the signature `(err?: Error) -> void`. The handler functions are called in order of registration. `callback` is called after all the handlers are called. - This is also a commonly used pattern for events like `emit`, `run`. - -- __Async waterfall__ The plugins will be applied asynchronously in the waterfall manner. - - - Defined using `AsyncWaterfallHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - The plugin handler functions are called with the current value and a callback function with the signature `(err: Error, nextValue: any) -> void.` When called `nextValue` is the current value for the next handler. The current value for the first handler is `init`. After all handlers are applied, callback is called with the last value. If any handler passes a value for `err`, the callback is called with this error and no more handlers are called. - This plugin pattern is expected for events like `before-resolve` and `after-resolve`. - -- __Async Series Bail__ - - - Defined using `AsyncSeriesBailHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - someMethod() { - // Call a hook: - this.hooks.compilation.call(); - -- __Async Parallel__ - - - Defined using `AsyncParallelHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - -- __Async Series Bail__ - - - Defined using `AsyncSeriesBailHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - -# Plugin Patterns - -Plugins grant unlimited opportunity to perform customizations within the webpack build system. This allows you to create custom asset types, perform unique build modifications, or even enhance the webpack runtime while using middleware. The following are some features of webpack that become useful while writing plugins. - -## Exploring assets, chunks, modules, and dependencies - -After a compilation is sealed, all structures within the compilation may be traversed. - -```javascript -class MyPlugin { - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - // Explore each chunk (build output): - compilation.chunks.forEach(chunk => { - // Explore each module within the chunk (built inputs): - chunk.modules.forEach(module => { - // Explore each source file path that was included into the module: - module.fileDependencies.forEach(filepath => { - // we've learned a lot about the source structure now... - }); - }); - - // Explore each asset filename generated by the chunk: - chunk.files.forEach(filename => { - // Get the asset source for each file generated by the chunk: - var source = compilation.assets[filename].source(); - }); - }); - - callback(); - }); - } -} -module.exports = MyPlugin; -``` - -- `compilation.modules`: An array of modules (built inputs) in the compilation. Each module manages the build of a raw file from your source library. -- `module.fileDependencies`: An array of source file paths included into a module. This includes the source JavaScript file itself (ex: `index.js`), and all dependency asset files (stylesheets, images, etc) that it has required. Reviewing dependencies is useful for seeing what source files belong to a module. -- `compilation.chunks`: An array of chunks (build outputs) in the compilation. Each chunk manages the composition of a final rendered assets. -- `chunk.modules`: An array of modules that are included into a chunk. By extension, you may look through each module's dependencies to see what raw source files fed into a chunk. -- `chunk.files`: An array of output filenames generated by the chunk. You may access these asset sources from the `compilation.assets` table. - -### Monitoring the watch graph - -While running webpack middleware, each compilation includes a `fileDependencies` array (what files are being watched) and a `fileTimestamps` hash that maps watched file paths to a timestamp. These are extremely useful for detecting what files have changed within the compilation: - -```javascript -class MyPlugin { - constructor() { - this.startTime = Date.now(); - this.prevTimestamps = {}; - } - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - var changedFiles = Object.keys(compilation.fileTimestamps).filter( - watchfile => { - return ( - (this.prevTimestamps[watchfile] || this.startTime) < - (compilation.fileTimestamps[watchfile] || Infinity) - ); - } - ); - - this.prevTimestamps = compilation.fileTimestamps; - callback(); - }); - } -} - -module.exports = MyPlugin; -``` - -You may also feed new file paths into the watch graph to receive compilation triggers when those files change. Simply push valid file paths into the `compilation.fileDependencies` array to add them to the watch. Note: the `fileDependencies` array is rebuilt in each compilation, so your plugin must push its own watched dependencies into each compilation to keep them under watch. - -## Changed chunks - -Similar to the watch graph, it's fairly simple to monitor changed chunks (or modules, for that matter) within a compilation by tracking their hashes. - -```javascript -class MyPlugin { - constructor() { - this.chunkVersions = {}; - } - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - var changedChunks = compilation.chunks.filter(chunk => { - var oldVersion = this.chunkVersions[chunk.name]; - this.chunkVersions[chunk.name] = chunk.hash; - return chunk.hash !== oldVersion; - }); - callback(); - }); - } -} - -module.exports = MyPlugin; -``` - - -# Release Process - -The release process for deploying webpack is actually quite painless. Read through the following steps, so you have a clear understanding of how it's done. - - -## Pull Requests - -When merging pull requests into the `master` branch, select the _Create Merge Commit_ option. - - -## Releasing - -```sh -npm version patch && git push --follow-tags && npm publish -npm version minor && git push --follow-tags && npm publish -npm version major && git push --follow-tags && npm publish -``` - -_This will increment the package version, commits the changes, cuts a __local tag__, push to github & publish the npm package._ - -After that go to the github [releases page](https://github.com/webpack/webpack/releases) and write a Changelog for the new tag. - - -# Debugging - -When contributing to the core repo, writing a loader/plugin, or even just working on complex project, debugging tools can be central to your workflow. Whether the problem is slow performance on a large project or an unhelpful traceback, the following utilities can make figuring it out less painful. - -- The [`stats` data](/api/stats) made available through [Node](/api/node#stats-object) and the [CLI](/api/cli#common-options). -- Chrome __DevTools__ via `node-nightly` and the latest Node.js versions. - - -## Stats - -Whether you want to sift through [this data](/api/stats) manually or use a tool to process it, the `stats` data can be extremely useful when debugging build issues. We won't go in depth here as there's an [entire page](/api/stats) dedicated to its contents, but know that you can use it to find the following information: - -- The contents of every module. -- The modules contained within every chunk. -- Per module compilation and resolving stats. -- Build errors and warnings. -- The relationships between modules. -- And much more... - -On top of that, the official [analyze tool](https://github.com/webpack/analyse) and [various others](/guides/code-splitting#bundle-analysis) will accept this data and visualize it in various ways. - - -## DevTools - -While [`console`](https://nodejs.org/api/console.html) statements may work well in simpler scenarios, sometimes a more robust solution is needed. As most front-end developers already know, Chrome DevTools are a life saver when debugging web applications, _but they don’t have to stop there_. As of Node v6.3.0+, developers can use the built-in `--inspect` flag to debug a node program in DevTools. - -This gives you the power to easily create breakpoints, debug memory usage, expose and examine objects in the console, and much more. In this short demo, we'll utilize the [`node-nightly`](https://github.com/hemanth/node-nightly) package which provides access to the latest and greatest inspecting capabilities. - -W> The `--inspect` interface has been available since v6.3.0 so feel to try it out with your local version, but be warned that certain features and flags may differ from the ones in this demo. - -Let's start by installing it globally: - -``` bash -npm install --global node-nightly -``` - -Now, we'll need to run it once to finish the installation: - -``` bash -node-nightly -``` - -Now, we can simply use `node-nightly` along with the `--inspect` flag to start our build in any webpack-based project. Note that we cannot run NPM `scripts`, e.g. `npm run build`, so we'll have specify the full `node_modules` path: - -``` bash -node-nightly --inspect ./node_modules/webpack/bin/webpack.js -``` - -Which should output something like: - -``` bash -Debugger listening on ws://127.0.0.1:9229/c624201a-250f-416e-a018-300bbec7be2c -For help see https://nodejs.org/en/docs/inspector -``` - -Now jump to `chrome://inspect` in the browser and you should see any active scripts you've inspected under the _Remote Target_ header. Click the "inspect" link under each script to open a dedicated debugger or the _Open dedicated DevTools for Node_ link for a session that will connect automatically. You can also check out the [NiM extension](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj), a handy Chrome plugin that will automatically open a DevTools tab every time you `--inspect` a script. - -We recommend using the `--inspect-brk` flag which will break on the first statement of the script allowing you to go through the source to set breakpoints and start/stop the build as you please. Also, don't forget that you can still pass arguments to the script. For example, if you have multiple configuration files you could pass `--config webpack.prod.js` to specify the configuration you'd like to debug. diff --git a/src/content/guides/_guides_all.md b/src/content/guides/_guides_all.md deleted file mode 100644 index dab542340ea2..000000000000 --- a/src/content/guides/_guides_all.md +++ /dev/null @@ -1,4880 +0,0 @@ - - -# Installation - -This guide goes through the various methods used to install webpack. - - -## Prerequisites - -Before we begin, make sure you have a fresh version of [Node.js](https://nodejs.org/en/) installed. The current Long Term Support (LTS) release is an ideal starting point. You may run into a variety of issues with the older versions as they may be missing functionality webpack and/or its related packages require. - - -## Local Installation - -The latest webpack release is: - -[](https://github.com/webpack/webpack/releases) - -To install the latest release or a specific version, run one of the following commands: - -``` bash -npm install --save-dev webpack -npm install --save-dev webpack@<version> -``` - -If you're using webpack v4 or later, you'll need to install the [CLI](/api/cli/). - -``` bash -npm install --save-dev webpack-cli -``` - -Installing locally is what we recommend for most projects. This makes it easier to upgrade projects individually when breaking changes are introduced. Typically webpack is run via one or more [npm scripts](https://docs.npmjs.com/misc/scripts) which will look for a webpack installation in your local `node_modules` directory: - -```json -"scripts": { - "start": "webpack --config webpack.config.js" -} -``` - -T> To run the local installation of webpack you can access its bin version as `node_modules/.bin/webpack`. - - -## Global Installation - -The following NPM installation will make `webpack` available globally: - -``` bash -npm install --global webpack -``` - -W> Note that this is __not a recommended practice__. Installing globally locks you down to a specific version of webpack and could fail in projects that use a different version. - - -## Bleeding Edge - -If you are enthusiastic about using the latest that webpack has to offer, you can install beta versions or even directly from the webpack repository using the following commands: - -``` bash -npm install webpack@beta -npm install webpack/webpack#<tagname/branchname> -``` - -W> Take caution when installing these bleeding edge releases! They may still contain bugs and therefore should not be used in production. - - -# Getting Started - -Webpack is used to compile JavaScript modules. Once [installed](/guides/installation), you can interface with webpack either from its [CLI](/api/cli) or [API](/api/node). If you're still new to webpack, please read through the [core concepts](/concepts) and [this comparison](/comparison) to learn why you might use it over the other tools that are out in the community. - -## Basic Setup - -First let's create a directory, initialize npm, [install webpack locally](/guides/installation#local-installation), and install the webpack-cli (the tool used to run webpack on the command line): - -``` bash -mkdir webpack-demo && cd webpack-demo -npm init -y -npm install webpack webpack-cli --save-dev -``` - -T> Throughout the Guides we will use `diff` blocks to show you what changes we're making to directories, files, and code. - -Now we'll create the following directory structure, files and their contents: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- index.html -+ |- /src -+ |- index.js -``` - -__src/index.js__ - -``` javascript -function component() { - let element = document.createElement('div'); - - // Lodash, currently included via a script, is required for this line to work - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; -} - -document.body.appendChild(component()); -``` - -__index.html__ - -``` html -<!doctype html> -<html> - <head> - <title>Getting Started</title> - <script src="https://unpkg.com/lodash@4.16.6"></script> - </head> - <body> - <script src="./src/index.js"></script> - </body> -</html> -``` - -We also need to adjust our `package.json` file in order to make sure we mark our package as `private`, as well as removing the `main` entry. This is to prevent an accidental publish of your code. - -T> If you want to learn more about the inner workings of `package.json`, then we recommend reading the [npm documentation](https://docs.npmjs.com/files/package.json). - -__package.json__ - -``` diff - { - "name": "webpack-demo", - "version": "1.0.0", - "description": "", -+ "private": true, -- "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "webpack": "^4.20.2", - "webpack-cli": "^3.1.2" - }, - "dependencies": {} - } -``` - -In this example, there are implicit dependencies between the `<script>` tags. Our `index.js` file depends on `lodash` being included in the page before it runs. This is because `index.js` never explicitly declared a need for `lodash`; it just assumes that the global variable `_` exists. - -There are problems with managing JavaScript projects this way: - -- It is not immediately apparent that the script depends on an external library. -- If a dependency is missing, or included in the wrong order, the application will not function properly. -- If a dependency is included but not used, the browser will be forced to download unnecessary code. - -Let's use webpack to manage these scripts instead. - -## Creating a Bundle - -First we'll tweak our directory structure slightly, separating the "source" code (`/src`) from our "distribution" code (`/dist`). The "source" code is the code that we'll write and edit. The "distribution" code is the minimized and optimized `output` of our build process that will eventually be loaded in the browser: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- /dist -+ |- index.html -- |- index.html - |- /src - |- index.js -``` - -To bundle the `lodash` dependency with `index.js`, we'll need to install the library locally: - -``` bash -npm install --save lodash -``` - -T> When installing a package that will be bundled into your production bundle, you should use `npm install --save`. If you're installing a package for development purposes (e.g. a linter, testing libraries, etc.) then you should use `npm install --save-dev`. More information can be found in the [npm documentation](https://docs.npmjs.com/cli/install). - -Now, lets import `lodash` in our script: - -__src/index.js__ - -``` diff -+ import _ from 'lodash'; -+ - function component() { - let element = document.createElement('div'); - -- // Lodash, currently included via a script, is required for this line to work - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -Now, since we'll be bundling our scripts, we have to update our `index.html` file. Let's remove the lodash `<script>`, as we now `import` it, and modify the other `<script>` tag to load the bundle, instead of the raw `/src` file: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> - <title>Getting Started</title> -- <script src="https://unpkg.com/lodash@4.16.6"></script> - </head> - <body> -- <script src="./src/index.js"></script> -+ <script src="main.js"></script> - </body> - </html> -``` - -In this setup, `index.js` explicitly requires `lodash` to be present, and binds it as `_` (no global scope pollution). By stating what dependencies a module needs, webpack can use this information to build a dependency graph. It then uses the graph to generate an optimized bundle where scripts will be executed in the correct order. - -With that said, let's run `npx webpack`, which will take our script at `src/index.js` as the [entry point](/concepts/entry-points), and will generate `dist/main.js` as the [output](/concepts/output). The `npx` command, which ships with Node 8.2/npm 5.2.0 or higher, runs the webpack binary (`./node_modules/.bin/webpack`) of the webpack package we installed in the beginning: - -``` bash -npx webpack - -... -Built at: 13/06/2018 11:52:07 - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ -``` - -T> Your output may vary a bit, but if the build is successful then you are good to go. Also, don't worry about the warning, we'll tackle that later. - -Open `index.html` in your browser and, if everything went right, you should see the following text: 'Hello webpack'. - - -## Modules - -The [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) statements have been standardized in [ES2015](https://babeljs.io/learn-es2015/) and [are supported in most browsers](https://caniuse.com/#search=modules). Some older browsers still lag behind but webpack supports modules out of the box. - -Behind the scenes, webpack actually "transpiles" the code so that older browsers can also run it. If you inspect `dist/main.js`, you might be able to see how webpack does this, it's quite ingenious! Besides `import` and `export`, webpack supports various other module syntaxes as well, see [Module API](/api/module-methods) for more information. - -Note that webpack will not alter any code other than `import` and `export` statements. If you are using other [ES2015 features](http://es6-features.org/), make sure to [use a transpiler](/loaders/#transpiling) such as [Babel](https://babeljs.io/) or [Bublé](https://buble.surge.sh/guide/) via webpack's [loader system](/concepts/loaders/). - - -## Using a Configuration - -As of version 4, webpack doesn't require any configuration, but most projects will need a more complex setup, which is why webpack supports a [configuration file](/concepts/configuration). This is much more efficient than having to manually type in a lot of commands in the terminal, so let's create one: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- webpack.config.js - |- /dist - |- index.html - |- /src - |- index.js -``` - -__webpack.config.js__ - -``` javascript -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'main.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -Now, let's run the build again but instead using our new configuration file: - -``` bash -npx webpack --config webpack.config.js - -... - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ -``` - -T> If a `webpack.config.js` is present, the `webpack` command picks it up by default. We use the `--config` option here only to show that you can pass a config of any name. This will be useful for more complex configurations that need to be split into multiple files. - -A configuration file allows far more flexibility than simple CLI usage. We can specify loader rules, plugins, resolve options and many other enhancements this way. See the [configuration documentation](/configuration) to learn more. - - -## NPM Scripts - -Given it's not particularly fun to run a local copy of webpack from the CLI, we can set up a little shortcut. Let's adjust our _package.json_ by adding an [npm script](https://docs.npmjs.com/misc/scripts): - -__package.json__ - -``` diff - { - "name": "webpack-demo", - "version": "1.0.0", - "description": "", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", -+ "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "webpack": "^4.20.2", - "webpack-cli": "^3.1.2" - }, - "dependencies": { - "lodash": "^4.17.5" - } - } -``` - -Now the `npm run build` command can be used in place of the `npx` command we used earlier. Note that within `scripts` we can reference locally installed npm packages by name the same way we did with `npx`. This convention is the standard in most npm-based projects because it allows all contributors to use the same set of common scripts (each with flags like `--config` if necessary). - -Now run the following command and see if your script alias works: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/. -``` - -T> Custom parameters can be passed to webpack by adding two dashes between the `npm run build` command and your parameters, e.g. `npm run build -- --colors`. - - -## Conclusion - -Now that you have a basic build together you should move on to the next guide [`Asset Management`](/guides/asset-management) to learn how to manage assets like images and fonts with webpack. At this point, your project should look like this: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist - |- main.js - |- index.html -|- /src - |- index.js -|- /node_modules -``` - -T> If you're using npm 5, you'll probably also see a `package-lock.json` file in your directory. - -If you want to learn more about webpack's design, you can check out the [basic concepts](/concepts) and [configuration](/configuration) pages. Furthermore, the [API](/api) section digs into the various interfaces webpack offers. - - -# Asset Management - -If you've been following the guides from the start, you will now have a small project that shows "Hello webpack". Now let's try to incorporate some other assets, like images, to see how they can be handled. - -Prior to webpack, front-end developers would use tools like grunt and gulp to process these assets and move them from their `/src` folder into their `/dist` or `/build` directory. The same idea was used for JavaScript modules, but tools like webpack will __dynamically bundle__ all dependencies (creating what's known as a [dependency graph](/concepts/dependency-graph)). This is great because every module now _explicitly states its dependencies_ and we'll avoid bundling modules that aren't in use. - -One of the coolest webpack features is that you can also _include any other type of file_, besides JavaScript, for which there is a loader. This means that the same benefits listed above for JavaScript (e.g. explicit dependencies) can be applied to everything used in building a website or web app. Let's start with CSS, as you may already be familiar with that setup. - -## Setup - -Let's make a minor change to our project before we get started: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> -- <title>Getting Started</title> -+ <title>Asset Management</title> - </head> - <body> -- <script src="./main.js"></script> -+ <script src="./bundle.js"></script> - </body> - </html> -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { -- filename: 'main.js', -+ filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - - -## Loading CSS - -In order to `import` a CSS file from within a JavaScript module, you need to install and add the [style-loader](/loaders/style-loader) and [css-loader](/loaders/css-loader) to your [`module` configuration](/configuration/module): - -``` bash -npm install --save-dev style-loader css-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ module: { -+ rules: [ -+ { -+ test: /\.css$/, -+ use: [ -+ 'style-loader', -+ 'css-loader' -+ ] -+ } -+ ] -+ } - }; -``` - -T> webpack uses a regular expression to determine which files it should look for and serve to a specific loader. In this case any file that ends with `.css` will be served to the `style-loader` and the `css-loader`. - -This enables you to `import './style.css'` into the file that depends on that styling. Now, when that module is run, a `<style>` tag with the stringified css will be inserted into the `<head>` of your html file. - -Let's try it out by adding a new `style.css` file to our project and import it in our `index.js`: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- style.css - |- index.js - |- /node_modules -``` - -__src/style.css__ - -``` css -.hello { - color: red; -} -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import './style.css'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.classList.add('hello'); - - return element; - } - - document.body.appendChild(component()); -``` - -Now run your build command: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -bundle.js 76.4 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -Open up `index.html` in your browser again and you should see that `Hello webpack` is now styled in red. To see what webpack did, inspect the page (don't view the page source, as it won't show you the result) and look at the page's head tags. It should contain our style block that we imported in `index.js`. - -Note that you can, and in most cases should, [minimize css](/plugins/mini-css-extract-plugin/#minimizing-for-production) for better load times in production. On top of that, loaders exist for pretty much any flavor of CSS you can think of -- [postcss](/loaders/postcss-loader), [sass](/loaders/sass-loader), and [less](/loaders/less-loader) to name a few. - - -## Loading Images - -So now we're pulling in our CSS, but what about our images like backgrounds and icons? Using the [file-loader](/loaders/file-loader) we can easily incorporate those in our system as well: - -``` bash -npm install --save-dev file-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, -+ { -+ test: /\.(png|svg|jpg|gif)$/, -+ use: [ -+ 'file-loader' -+ ] -+ } - ] - } - }; -``` - -Now, when you `import MyImage from './my-image.png'`, that image will be processed and added to your `output` directory _and_ the `MyImage` variable will contain the final url of that image after processing. When using the [css-loader](/loaders/css-loader), as shown above, a similar process will occur for `url('./my-image.png')` within your CSS. The loader will recognize this is a local file, and replace the `'./my-image.png'` path with the final path to the image in your `output` directory. The [html-loader](/loaders/html-loader) handles `<img src="./my-image.png" />` in the same manner. - -Let's add an image to our project and see how this works, you can use any image you like: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; - import './style.css'; -+ import Icon from './icon.png'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - element.classList.add('hello'); - -+ // Add the image to our existing div. -+ var myIcon = new Image(); -+ myIcon.src = Icon; -+ -+ element.appendChild(myIcon); - - return element; - } - - document.body.appendChild(component()); -``` - -__src/style.css__ - -``` diff - .hello { - color: red; -+ background: url('./icon.png'); - } -``` - -Let's create a new build and open up the index.html file again: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] - bundle.js 76.7 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -If all went well, you should now see your icon as a repeating background, as well as an `img` element beside our `Hello webpack` text. If you inspect this element, you'll see that the actual filename has changed to something like `5c999da72346a995e7e2718865d019c8.png`. This means webpack found our file in the `src` folder and processed it! - -T> A logical next step from here is minifying and optimizing your images. Check out the [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader) and [url-loader](/loaders/url-loader) for more on how you can enhance your image loading process. - - -## Loading Fonts - -So what about other assets like fonts? The file and url loaders will take any file you load through them and output it to your build directory. This means we can use them for any kind of file, including fonts. Let's update our `webpack.config.js` to handle font files: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, - { - test: /\.(png|svg|jpg|gif)$/, - use: [ - 'file-loader' - ] - }, -+ { -+ test: /\.(woff|woff2|eot|ttf|otf)$/, -+ use: [ -+ 'file-loader' -+ ] -+ } - ] - } - }; -``` - -Add some font files to your project: - -__project__ - - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- my-font.woff -+ |- my-font.woff2 - |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -With the loader configured and fonts in place, you can incorporate them via an `@font-face` declaration. The local `url(...)` directive will be picked up by webpack just as it was with the image: - -__src/style.css__ - -``` diff -+ @font-face { -+ font-family: 'MyFont'; -+ src: url('./my-font.woff2') format('woff2'), -+ url('./my-font.woff') format('woff'); -+ font-weight: 600; -+ font-style: normal; -+ } - - .hello { - color: red; -+ font-family: 'MyFont'; - background: url('./icon.png'); - } -``` - -Now run a new build and let's see if webpack handled our fonts: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -5439466351d432b73fdb518c6ae9654a.woff2 19.5 KiB [emitted] - 387c65cc923ad19790469cfb5b7cb583.woff 23.4 KiB [emitted] - da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] - bundle.js 77 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -Open up `index.html` again and see if our `Hello webpack` text has changed to the new font. If all is well, you should see the changes. - - -## Loading Data - -Another useful asset that can be loaded is data, like JSON files, CSVs, TSVs, and XML. Support for JSON is actually built-in, similar to NodeJS, meaning `import Data from './data.json'` will work by default. To import CSVs, TSVs, and XML you could use the [csv-loader](https://github.com/theplatapi/csv-loader) and [xml-loader](https://github.com/gisikw/xml-loader). Let's handle loading all three: - -``` bash -npm install --save-dev csv-loader xml-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, - { - test: /\.(png|svg|jpg|gif)$/, - use: [ - 'file-loader' - ] - }, - { - test: /\.(woff|woff2|eot|ttf|otf)$/, - use: [ - 'file-loader' - ] - }, -+ { -+ test: /\.(csv|tsv)$/, -+ use: [ -+ 'csv-loader' -+ ] -+ }, -+ { -+ test: /\.xml$/, -+ use: [ -+ 'xml-loader' -+ ] -+ } - ] - } - }; -``` - -Add some data files to your project: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- data.xml - |- my-font.woff - |- my-font.woff2 - |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -__src/data.xml__ - -``` xml -<?xml version="1.0" encoding="UTF-8"?> -<note> - <to>Mary</to> - <from>John</from> - <heading>Reminder</heading> - <body>Call Cindy on Tuesday</body> -</note> -``` - -Now you can `import` any one of those four types of data (JSON, CSV, TSV, XML) and the `Data` variable you import it to will contain parsed JSON for easy consumption: - -__src/index.js__ - -``` diff - import _ from 'lodash'; - import './style.css'; - import Icon from './icon.png'; -+ import Data from './data.xml'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - element.classList.add('hello'); - - // Add the image to our existing div. - var myIcon = new Image(); - myIcon.src = Icon; - - element.appendChild(myIcon); - -+ console.log(Data); - - return element; - } - - document.body.appendChild(component()); -``` - -When you open `index.html` and look at your console in your developer tools, you should be able to see your imported data being logged to the console! - -T> This can be especially helpful when implementing some sort of data visualization using a tool like [d3](https://github.com/d3). Instead of making an ajax request and parsing the data at runtime you can load it into your module during the build process so that the parsed data is ready to go as soon as the module hits the browser. - - -## Global Assets - -The coolest part of everything mentioned above, is that loading assets this way allows you to group modules and assets together in a more intuitive way. Instead of relying on a global `/assets` directory that contains everything, you can group assets with the code that uses them. For example, a structure like this can be very useful: - -``` diff -- |- /assets -+ |– /components -+ | |– /my-component -+ | | |– index.jsx -+ | | |– index.css -+ | | |– icon.svg -+ | | |– img.png -``` - -This setup makes your code a lot more portable as everything that is closely coupled now lives together. Let's say you want to use `/my-component` in another project, simply copy or move it into the `/components` directory over there. As long as you've installed any _external dependencies_ and your _configuration has the same loaders_ defined, you should be good to go. - -However, let's say you're locked into your old ways or you have some assets that are shared between multiple components (views, templates, modules, etc.). It's still possible to store these assets in a base directory and even use [aliasing](/configuration/resolve#resolve-alias) to make them easier to `import`. - - -## Wrapping up - -For the next guides we won't be using all the different assets we've used in this guide, so let's do some cleanup so we're prepared for the next piece of the guides [Output Management](https://webpack.js.org/guides/output-management/): - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -- |- data.xml -- |- my-font.woff -- |- my-font.woff2 -- |- icon.png -- |- style.css - |- index.js - |- /node_modules -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- module: { -- rules: [ -- { -- test: /\.css$/, -- use: [ -- 'style-loader', -- 'css-loader' -- ] -- }, -- { -- test: /\.(png|svg|jpg|gif)$/, -- use: [ -- 'file-loader' -- ] -- }, -- { -- test: /\.(woff|woff2|eot|ttf|otf)$/, -- use: [ -- 'file-loader' -- ] -- }, -- { -- test: /\.(csv|tsv)$/, -- use: [ -- 'csv-loader' -- ] -- }, -- { -- test: /\.xml$/, -- use: [ -- 'xml-loader' -- ] -- } -- ] -- } - }; -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -- import './style.css'; -- import Icon from './icon.png'; -- import Data from './data.xml'; -- - function component() { - var element = document.createElement('div'); -- -- // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- element.classList.add('hello'); -- -- // Add the image to our existing div. -- var myIcon = new Image(); -- myIcon.src = Icon; -- -- element.appendChild(myIcon); -- -- console.log(Data); - - return element; - } - - document.body.appendChild(component()); -``` - - -## Next guide - -Let's move on to [Output Management](https://webpack.js.org/guides/output-management/) - - -## Further Reading - -- [Loading Fonts](https://survivejs.com/webpack/loading/fonts/) on SurviveJS - - -# Output Management - -T> This guide extends on code examples found in the [`Asset Management`](/guides/asset-management) guide. - -So far we've manually included all our assets in our `index.html` file, but as your application grows and once you start [using hashes in filenames](/guides/caching) and outputting [multiple bundles](/guides/code-splitting), it will be difficult to keep managing your `index.html` file manually. However, a few plugins exist that will make this process much easier to manage. - -## Preparation - -First, let's adjust our project a little bit: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js -+ |- print.js - |- /node_modules -``` - -Let's add some logic to our `src/print.js` file: - -__src/print.js__ - -``` js -export default function printMe() { - console.log('I get called from print.js!'); -} -``` - -And use that function in our `src/index.js` file: - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); -+ var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - -+ btn.innerHTML = 'Click me and check the console!'; -+ btn.onclick = printMe; -+ -+ element.appendChild(btn); - - return element; - } - - document.body.appendChild(component()); -``` - -Let's also update our `dist/index.html` file, in preparation for webpack to split out entries: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> -- <title>Asset Management</title> -+ <title>Output Management</title> -+ <script src="./print.bundle.js"></script> - </head> - <body> -- <script src="./bundle.js"></script> -+ <script src="./app.bundle.js"></script> - </body> - </html> -``` - -Now adjust the config. We'll be adding our `src/print.js` as a new entry point (`print`) and we'll change the output as well, so that it will dynamically generate bundle names, based on the entry point names: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { -- entry: './src/index.js', -+ entry: { -+ app: './src/index.js', -+ print: './src/print.js' -+ }, - output: { -- filename: 'bundle.js', -+ filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Let's run `npm run build` and see what this generates: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 545 kB 0, 1 [emitted] [big] app -print.bundle.js 2.74 kB 1 [emitted] print -... -``` - -We can see that webpack generates our `print.bundle.js` and `app.bundle.js` files, which we also specified in our `index.html` file. if you open `index.html` in your browser, you can see what happens when you click the button. - -But what would happen if we changed the name of one of our entry points, or even added a new one? The generated bundles would be renamed on a build, but our `index.html` file would still reference the old names. Let's fix that with the [`HtmlWebpackPlugin`](/plugins/html-webpack-plugin). - - -## Setting up HtmlWebpackPlugin - -First install the plugin and adjust the `webpack.config.js` file: - -``` bash -npm install --save-dev html-webpack-plugin -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, -+ plugins: [ -+ new HtmlWebpackPlugin({ -+ title: 'Output Management' -+ }) -+ ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Before we do a build, you should know that the `HtmlWebpackPlugin` by default will generate its own `index.html` file, even though we already have one in the `dist/` folder. This means that it will replace our `index.html` file with a newly generated one. Let's see what happens when we do an `npm run build`: - -``` bash -... - Asset Size Chunks Chunk Names - print.bundle.js 544 kB 0 [emitted] [big] print - app.bundle.js 2.81 kB 1 [emitted] app - index.html 249 bytes [emitted] -... -``` - -If you open `index.html` in your code editor, you'll see that the `HtmlWebpackPlugin` has created an entirely new file for you and that all the bundles are automatically added. - -If you want to learn more about all the features and options that the `HtmlWebpackPlugin` provides, then you should read up on it on the [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin) repo. - -You can also take a look at [`html-webpack-template`](https://github.com/jaketrent/html-webpack-template) which provides a couple of extra features in addition to the default template. - - -## Cleaning up the `/dist` folder - -As you might have noticed over the past guides and code example, our `/dist` folder has become quite cluttered. Webpack will generate the files and put them in the `/dist` folder for you, but it doesn't keep track of which files are actually in use by your project. - -In general it's good practice to clean the `/dist` folder before each build, so that only used files will be generated. Let's take care of that. - -A popular plugin to manage this is the [`clean-webpack-plugin`](https://www.npmjs.com/package/clean-webpack-plugin) so let's install and configure it. - -``` bash -npm install --save-dev clean-webpack-plugin -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); -+ const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ -+ new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Output Management' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Now run an `npm run build` and inspect the `/dist` folder. If everything went well you should now only see the files generated from the build and no more old files! - - -## The Manifest - -You might be wondering how webpack and its plugins seem to "know" what files are being generated. The answer is in the manifest that webpack keeps to track how all the modules map to the output bundles. If you're interested in managing webpack's [`output`](/configuration/output) in other ways, the manifest would be a good place to start. - -The manifest data can be extracted into a json file for easy consumption using the [`WebpackManifestPlugin`](https://github.com/danethurber/webpack-manifest-plugin). - -We won't go through a full example of how to use this plugin within your projects, but you can read up on [the concept page](/concepts/manifest) and the [caching guide](/guides/caching) to find out how this ties into long term caching. - - -## Conclusion - -Now that you've learned about dynamically adding bundles to your HTML, let's dive into the [development guide](/guides/development). Or, if you want to dig into more advanced topics, we would recommend heading over to the [code splitting guide](/guides/code-splitting). - - -# Development - -T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. - -If you've been following the guides, you should have a solid understanding of some of the webpack basics. Before we continue, let's look into setting up a development environment to make our lives a little easier. - -W> The tools in this guide are __only meant for development__, please __avoid__ using them in production! - -Before proceeding lets first set [`mode` to `'development'`](/concepts/mode/#mode-development). - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { -+ mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -## Using source maps - -When webpack bundles your source code, it can become difficult to track down errors and warnings to their original location. For example, if you bundle three source files (`a.js`, `b.js`, and `c.js`) into one bundle (`bundle.js`) and one of the source files contains an error, the stack trace will simply point to `bundle.js`. This isn't always helpful as you probably want to know exactly which source file the error came from. - -In order to make it easier to track down errors and warnings, JavaScript offers [source maps](http://blog.teamtreehouse.com/introduction-source-maps), which maps your compiled code back to your original source code. If an error originates from `b.js`, the source map will tell you exactly that. - -There are a lot of [different options](/configuration/devtool) available when it comes to source maps. Be sure to check them out so you can configure them to your needs. - -For this guide, let's use the `inline-source-map` option, which is good for illustrative purposes (though not for production): - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, -+ devtool: 'inline-source-map', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Now let's make sure we have something to debug, so let's create an error in our `print.js` file: - -__src/print.js__ - -``` diff - export default function printMe() { -- console.log('I get called from print.js!'); -+ cosnole.log('I get called from print.js!'); - } -``` - -Run an `npm run build`, it should compile to something like this: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 1.44 MB 0, 1 [emitted] [big] app -print.bundle.js 6.43 kB 1 [emitted] print - index.html 248 bytes [emitted] -... -``` - -Now open the resulting `index.html` file in your browser. Click the button and look in your console where the error is displayed. The error should say something like this: - - ``` bash - Uncaught ReferenceError: cosnole is not defined - at HTMLButtonElement.printMe (print.js:2) - ``` - -We can see that the error also contains a reference to the file (`print.js`) and line number (2) where the error occurred. This is great because now we know exactly where to look in order to fix the issue. - - -## Choosing a Development Tool - -W> Some text editors have a "safe write" function that might interfere with some of the following tools. Read [Adjusting Your text Editor](#adjusting-your-text-editor) for a solution to these issues. - -It quickly becomes a hassle to manually run `npm run build` every time you want to compile your code. - -There are a couple of different options available in webpack that help you automatically compile your code whenever it changes: - - 1. webpack's Watch Mode - 2. webpack-dev-server - 3. webpack-dev-middleware - -In most cases, you probably would want to use `webpack-dev-server`, but let's explore all of the above options. - - -### Using Watch Mode - -You can instruct webpack to "watch" all files within your dependency graph for changes. If one of these files is updated, the code will be recompiled so you don't have to run the full build manually. - -Let's add an npm script that will start webpack's Watch Mode: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", -+ "watch": "webpack --watch", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now run `npm run watch` from the command line and see how webpack compiles your code. -You can see that it doesn't exit the command line because the script is currently watching your files. - -Now, while webpack is watching your files, let's remove the error we introduced earlier: - -__src/print.js__ - -``` diff - export default function printMe() { -- cosnole.log('I get called from print.js!'); -+ console.log('I get called from print.js!'); - } -``` - -Now save your file and check the terminal window. You should see that webpack automatically recompiles the changed module! - -The only downside is that you have to refresh your browser in order to see the changes. It would be much nicer if that would happen automatically as well, so let's try `webpack-dev-server` which will do exactly that. - - -### Using webpack-dev-server - -The `webpack-dev-server` provides you with a simple web server and the ability to use live reloading. Let's set it up: - -``` bash -npm install --save-dev webpack-dev-server -``` - -Change your config file to tell the dev server where to look for files: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - devtool: 'inline-source-map', -+ devServer: { -+ contentBase: './dist' -+ }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -This tells `webpack-dev-server` to serve the files from the `dist` directory on `localhost:8080`. - -W> webpack-dev-server doesn't write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server's root path. If your page expects to find the bundle files in different path, you can change this with the [`publicPath`](/configuration/dev-server/#devserver-publicpath-) option in the dev server's configuration. - -Let's add a script to easily run the dev server as well: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "watch": "webpack --watch", -+ "start": "webpack-dev-server --open", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now we can run `npm start` from the command line and we will see our browser automatically loading up our page. If you now change any of the source files and save them, the web server will automatically reload after the code has been compiled. Give it a try! - -The `webpack-dev-server` comes with many configurable options. Head over to the [documentation](/configuration/dev-server) to learn more. - -T> Now that your server is working, you might want to give [Hot Module Replacement](/guides/hot-module-replacement) a try! - - -### Using webpack-dev-middleware - -`webpack-dev-middleware` is a wrapper that will emit files processed by webpack to a server. This is used in `webpack-dev-server` internally, however it's available as a separate package to allow more custom setups if desired. We'll take a look at an example that combines webpack-dev-middleware with an express server. - -Let's install `express` and `webpack-dev-middleware` so we can get started: - -``` bash -npm install --save-dev express webpack-dev-middleware -``` - -Now we need to make some adjustments to our webpack configuration file in order to make sure the middleware will function correctly: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Output Management' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist'), -+ publicPath: '/' - } - }; -``` - -The `publicPath` will be used within our server script as well in order to make sure files are served correctly on `http://localhost:3000`. We'll specify the port number later. The next step is setting up our custom `express` server: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js -+ |- server.js - |- /dist - |- /src - |- index.js - |- print.js - |- /node_modules -``` - -__server.js__ - -```javascript -const express = require('express'); -const webpack = require('webpack'); -const webpackDevMiddleware = require('webpack-dev-middleware'); - -const app = express(); -const config = require('./webpack.config.js'); -const compiler = webpack(config); - -// Tell express to use the webpack-dev-middleware and use the webpack.config.js -// configuration file as a base. -app.use(webpackDevMiddleware(compiler, { - publicPath: config.output.publicPath -})); - -// Serve the files on port 3000. -app.listen(3000, function () { - console.log('Example app listening on port 3000!\n'); -}); -``` - -Now add an npm script to make it a little easier to run the server: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "watch": "webpack --watch", - "start": "webpack-dev-server --open", -+ "server": "node server.js", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "express": "^4.15.3", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "webpack-dev-middleware": "^1.12.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now in your terminal run `npm run server`, it should give you an output similar to this: - -``` bash -Example app listening on port 3000! -... - Asset Size Chunks Chunk Names - app.bundle.js 1.44 MB 0, 1 [emitted] [big] app -print.bundle.js 6.57 kB 1 [emitted] print - index.html 306 bytes [emitted] -... -webpack: Compiled successfully. -``` - -Now fire up your browser and go to `http://localhost:3000`. You should see your webpack app running and functioning! - -T> If you would like to know more about how Hot Module Replacement works, we recommend you read the [Hot Module Replacement](/guides/hot-module-replacement/) guide. - - -## Adjusting Your Text Editor - -When using automatic compilation of your code, you could run into issues when saving your files. Some editors have a "safe write" feature that can potentially interfere with recompilation. - -To disable this feature in some common editors, see the list below: - -- __Sublime Text 3__: Add `atomic_save: 'false'` to your user preferences. -- __JetBrains IDEs (e.g. WebStorm)__: Uncheck "Use safe write" in `Preferences > Appearance & Behavior > System Settings`. -- __Vim__: Add `:set backupcopy=yes` to your settings. - - -## Conclusion - -Now that you've learned how to automatically compile your code and run a simple development server, you can check out the next guide, which will cover [Hot Module Replacement](/guides/hot-module-replacement). - - -# Hot Module Replacement - -T> This guide extends on code examples found in the [Development](/guides/development) guide. - -Hot Module Replacement (or HMR) is one of the most useful features offered by webpack. It allows all kinds of modules to be updated at runtime without the need for a full refresh. This page focuses on __implementation__ while the [concepts page](/concepts/hot-module-replacement) gives more details on how it works and why it's useful. - -W> __HMR__ is not intended for use in production, meaning it should only be used in development. See the [building for production guide](/guides/production) for more information. - - -## Enabling HMR - -This feature is great for productivity. All we need to do is update our [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration, and use webpack's built in HMR plugin. We'll also remove the entry point for `print.js` as it will now be consumed by the `index.js` module. - -T> If you took the route of using `webpack-dev-middleware` instead of `webpack-dev-server`, please use the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom server or application. - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const webpack = require('webpack'); - - module.exports = { - entry: { -- app: './src/index.js', -- print: './src/print.js' -+ app: './src/index.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist', -+ hot: true - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Hot Module Replacement' - }), -+ new webpack.HotModuleReplacementPlugin() - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -T> You can use the CLI to modify the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration with the following command: `webpack-dev-server --hotOnly`. - -Now let's update the `index.js` file so that when a change inside `print.js` is detected we tell webpack to accept the updated module. - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; - - element.appendChild(btn); - - return element; - } - - document.body.appendChild(component()); -+ -+ if (module.hot) { -+ module.hot.accept('./print.js', function() { -+ console.log('Accepting the updated printMe module!'); -+ printMe(); -+ }) -+ } -``` - -Start changing the `console.log` statement in `print.js`, and you should see the following output in the browser console. - -__print.js__ - -``` diff - export default function printMe() { -- console.log('I get called from print.js!'); -+ console.log('Updating print.js...') - } -``` - -__console__ - -``` diff -[HMR] Waiting for update signal from WDS... -main.js:4395 [WDS] Hot Module Replacement enabled. -+ 2main.js:4395 [WDS] App updated. Recompiling... -+ main.js:4395 [WDS] App hot update... -+ main.js:4330 [HMR] Checking for updates on the server... -+ main.js:10024 Accepting the updated printMe module! -+ 0.4b8ee77….hot-update.js:10 Updating print.js... -+ main.js:4330 [HMR] Updated modules: -+ main.js:4330 [HMR] - 20 -``` - - -## Via the Node.js API - -When using Webpack Dev Server with the Node.js API, don't put the dev server options on the webpack config object. Instead, pass them as a second parameter upon creation. For example: - -`new WebpackDevServer(compiler, options)` - -To enable HMR, you also need to modify your webpack configuration object to include the HMR entry points. The `webpack-dev-server` package includes a method called `addDevServerEntrypoints` which you can use to do this. Here's a small example of how that might look: - -__dev-server.js__ - -``` javascript -const webpackDevServer = require('webpack-dev-server'); -const webpack = require('webpack'); - -const config = require('./webpack.config.js'); -const options = { - contentBase: './dist', - hot: true, - host: 'localhost' -}; - -webpackDevServer.addDevServerEntrypoints(config, options); -const compiler = webpack(config); -const server = new webpackDevServer(compiler, options); - -server.listen(5000, 'localhost', () => { - console.log('dev server listening on port 5000'); -}); -``` - -T> If you're [using `webpack-dev-middleware`](/guides/development#using-webpack-dev-middleware), check out the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom dev server. - - -## Gotchas - -Hot Module Replacement can be tricky. To show this, let's go back to our working example. If you go ahead and click the button on the example page, you will realize the console is printing the old `printMe` function. - -This is happening because the button's `onclick` event handler is still bound to the original `printMe` function. - -To make this work with HMR we need to update that binding to the new `printMe` function using `module.hot.accept`: - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; // onclick event is bind to the original printMe function - - element.appendChild(btn); - - return element; - } - -- document.body.appendChild(component()); -+ let element = component(); // Store the element to re-render on print.js changes -+ document.body.appendChild(element); - - if (module.hot) { - module.hot.accept('./print.js', function() { - console.log('Accepting the updated printMe module!'); -- printMe(); -+ document.body.removeChild(element); -+ element = component(); // Re-render the "component" to update the click handler -+ document.body.appendChild(element); - }) - } -``` - -This is just one example, but there are many others that can easily trip people up. Luckily, there are a lot of loaders out there (some of which are mentioned below) that will make hot module replacement much easier. - - -## HMR with Stylesheets - -Hot Module Replacement with CSS is actually fairly straightforward with the help of the `style-loader`. This loader uses `module.hot.accept` behind the scenes to patch `<style>` tags when CSS dependencies are updated. - -First let's install both loaders with the following command: - -```bash -npm install --save-dev style-loader css-loader -``` - -Now let's update the configuration file to make use of the loader. - -__webpack.config.js__ - -```diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const webpack = require('webpack'); - - module.exports = { - entry: { - app: './src/index.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist', - hot: true - }, -+ module: { -+ rules: [ -+ { -+ test: /\.css$/, -+ use: ['style-loader', 'css-loader'] -+ } -+ ] -+ }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Hot Module Replacement' - }), - new webpack.HotModuleReplacementPlugin() - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Hot loading stylesheets is as easy as importing them into a module: - -__project__ - -``` diff - webpack-demo - | - package.json - | - webpack.config.js - | - /dist - | - bundle.js - | - /src - | - index.js - | - print.js -+ | - styles.css -``` - -__styles.css__ - -``` css -body { - background: blue; -} -``` - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; -+ import './styles.css'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; // onclick event is bind to the original printMe function - - element.appendChild(btn); - - return element; - } - - let element = component(); - document.body.appendChild(element); - - if (module.hot) { - module.hot.accept('./print.js', function() { - console.log('Accepting the updated printMe module!'); - document.body.removeChild(element); - element = component(); // Re-render the "component" to update the click handler - document.body.appendChild(element); - }) - } - -``` - -Change the style on `body` to `background: red;` and you should immediately see the page's background color change without a full refresh. - -__styles.css__ - -``` diff - body { -- background: blue; -+ background: red; - } -``` - - -## Other Code and Frameworks - -There are many other loaders and examples out in the community to make HMR interact smoothly with a variety of frameworks and libraries... - -- [React Hot Loader](https://github.com/gaearon/react-hot-loader): Tweak react components in real time. -- [Vue Loader](https://github.com/vuejs/vue-loader): This loader supports HMR for vue components out of the box. -- [Elm Hot Loader](https://github.com/fluxxu/elm-hot-loader): Supports HMR for the Elm programming language. -- [Angular HMR](https://github.com/gdi2290/angular-hmr): No loader necessary! A simple change to your main NgModule file is all that's required to have full control over the HMR APIs. - -T> If you know of any other loaders or plugins that help with or enhance Hot Module Replacement please submit a pull request to add to this list! - - -# Tree Shaking - -_Tree shaking_ is a term commonly used in the JavaScript context for dead-code elimination. It relies on the [static structure](http://exploringjs.com/es6/ch_modules.html#static-module-structure) of ES2015 module syntax, i.e. [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export). The name and concept have been popularized by the ES2015 module bundler [rollup](https://github.com/rollup/rollup). - -The webpack 2 release came with built-in support for ES2015 modules (alias _harmony modules_) as well as unused module export detection. The new webpack 4 release expands on this capability with a way to provide hints to the compiler via the `"sideEffects"` `package.json` property to denote which files in your project are "pure" and therefore safe to prune if unused. - -T> The remainder of this guide will stem from [Getting Started](/guides/getting-started). If you haven't read through that guide already, please do so now. - - -## Add a Utility - -Let's add a new utility file to our project, `src/math.js`, that exports two functions: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist - |- bundle.js - |- index.html -|- /src - |- index.js -+ |- math.js -|- /node_modules -``` - -__src/math.js__ - -```javascript -export function square(x) { - return x * x; -} - -export function cube(x) { - return x * x * x; -} -``` - -Set the `mode` configuration option to [development](/concepts/mode/#mode-development) to make sure that the bundle is not minified: - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') -- } -+ }, -+ mode: 'development', -+ optimization: { -+ usedExports: true -+ } -}; -``` - -With that in place, let's update our entry script to utilize one of these new methods and remove `lodash` for simplicity: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -+ import { cube } from './math.js'; - - function component() { -- var element = document.createElement('div'); -+ var element = document.createElement('pre'); - -- // Lodash, now imported by this script -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.innerHTML = [ -+ 'Hello webpack!', -+ '5 cubed is equal to ' + cube(5) -+ ].join('\n\n'); - - return element; - } - - document.body.appendChild(component()); -``` - -Note that we __did not `import` the `square` method__ from the `src/math.js` module. That function is what's known as "dead code", meaning an unused `export` that should be dropped. Now let's run our npm script, `npm run build`, and inspect the output bundle: - -__dist/bundle.js (around lines 90 - 100)__ - -```js -/* 1 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - 'use strict'; - /* unused harmony export square */ - /* harmony export (immutable) */ __webpack_exports__['a'] = cube; - function square(x) { - return x * x; - } - - function cube(x) { - return x * x * x; - } -}); -``` - -Note the `unused harmony export square` comment above. If you look at the code below it, you'll notice that `square` is not being imported, however, it is still included in the bundle. We'll fix that in the next section. - - -## Mark the file as side-effect-free - -In a 100% ESM module world, identifying side effects is straightforward. However, we aren't there just yet, so in the mean time it's necessary to provide hints to webpack's compiler on the "pureness" of your code. - -The way this is accomplished is the `"sideEffects"` package.json property. - -```json -{ - "name": "your-project", - "sideEffects": false -} -``` - -All the code noted above does not contain side effects, so we can simply mark the property as `false` to inform webpack that it can safely prune unused exports. - -T> A "side effect" is defined as code that performs a special behavior when imported, other than exposing one or more exports. An example of this are polyfills, which affect the global scope and usually do not provide an export. - -If your code did have some side effects though, an array can be provided instead: - -```json -{ - "name": "your-project", - "sideEffects": [ - "./src/some-side-effectful-file.js" - ] -} -``` - -The array accepts relative, absolute, and glob patterns to the relevant files. It uses [micromatch](https://github.com/micromatch/micromatch#matching-features) under the hood. - -T> Note that any imported file is subject to tree shaking. This means if you use something like `css-loader` in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode: - -```json -{ - "name": "your-project", - "sideEffects": [ - "./src/some-side-effectful-file.js", - "*.css" - ] -} -``` - -Finally, `"sideEffects"` can also be set from the [`module.rules` configuration option](/configuration/module/#module-rules). - -## Minify the Output - -So we've cued up our "dead code" to be dropped by using the `import` and `export` syntax, but we still need to drop it from the bundle. To do that set the `mode` configuration option to [`production`](/concepts/mode/#mode-production) configuration option. - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- mode: 'development', -- optimization: { -- usedExports: true -- } -+ mode: 'production' -}; -``` - -T> Note that the `--optimize-minimize` flag can be used to enable `TerserPlugin` as well. - -With that squared away, we can run another `npm run build` and see if anything has changed. - -Notice anything different about `dist/bundle.js`? Clearly the whole bundle is now minified and mangled, but, if you look carefully, you won't see the `square` function included but will see a mangled version of the `cube` function (`function r(e){return e*e*e}n.a=r`). With minification and tree shaking our bundle is now a few bytes smaller! While that may not seem like much in this contrived example, tree shaking can yield a significant decrease in bundle size when working on larger applications with complex dependency trees. - -T> [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) is needed for the tree shaking to work. It is added by `mode: "production"`. If you are not using it, remember to add the [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) manually. - -## Conclusion - -So, what we've learned is that in order to take advantage of _tree shaking_, you must... - -- Use ES2015 module syntax (i.e. `import` and `export`). -- Ensure no compilers transform your ES2015 module syntax into CommonJS modules (this is the default behavior of popular Babel preset @babel/preset-env - see [documentation](https://babeljs.io/docs/en/babel-preset-env#modules) for more details). -- Add a `"sideEffects"` property to your project's `package.json` file. -- Use [`production`](/concepts/mode/#mode-production) `mode` configuration option to enable [various optimizations](/concepts/mode/#usage) including minification and tree shaking. - -You can imagine your application as a tree. The source code and libraries you actually use represent the green, living leaves of the tree. Dead code represents the brown, dead leaves of the tree that are consumed by autumn. In order to get rid of the dead leaves, you have to shake the tree, causing them to fall. - -If you are interested in more ways to optimize your output, please jump to the next guide for details on building for [production](/guides/production). - - -# Production - -In this guide we'll dive into some of the best practices and utilities for building a production site or application. - -T> This walkthrough stems from [Tree Shaking](/guides/tree-shaking) and [Development](/guides/development). Please ensure you are familiar with the concepts/setup introduced in those guides before continuing on. - - -## Setup - -The goals of _development_ and _production_ builds differ greatly. In _development_, we want strong source mapping and a localhost server with live reloading or hot module replacement. In _production_, our goals shift to a focus on minified bundles, lighter weight source maps, and optimized assets to improve load time. With this logical separation at hand, we typically recommend writing __separate webpack configurations__ for each environment. - -While we will separate the _production_ and _development_ specific bits out, note that we'll still maintain a "common" configuration to keep things DRY. In order to merge these configurations together, we'll use a utility called [`webpack-merge`](https://github.com/survivejs/webpack-merge). With the "common" configuration in place, we won't have to duplicate code within the environment-specific configurations. - -Let's start by installing `webpack-merge` and splitting out the bits we've already worked on in previous guides: - -``` bash -npm install --save-dev webpack-merge -``` - -__project__ - -``` diff - webpack-demo - |- package.json -- |- webpack.config.js -+ |- webpack.common.js -+ |- webpack.dev.js -+ |- webpack.prod.js - |- /dist - |- /src - |- index.js - |- math.js - |- /node_modules -``` - -__webpack.common.js__ - -``` diff -+ const path = require('path'); -+ const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const HtmlWebpackPlugin = require('html-webpack-plugin'); -+ -+ module.exports = { -+ entry: { -+ app: './src/index.js' -+ }, -+ plugins: [ -+ new CleanWebpackPlugin(['dist']), -+ new HtmlWebpackPlugin({ -+ title: 'Production' -+ }) -+ ], -+ output: { -+ filename: '[name].bundle.js', -+ path: path.resolve(__dirname, 'dist') -+ } -+ }; -``` - -__webpack.dev.js__ - -``` diff -+ const merge = require('webpack-merge'); -+ const common = require('./webpack.common.js'); -+ -+ module.exports = merge(common, { -+ mode: 'development', -+ devtool: 'inline-source-map', -+ devServer: { -+ contentBase: './dist' -+ } -+ }); -``` - -__webpack.prod.js__ - -``` diff -+ const merge = require('webpack-merge'); -+ const common = require('./webpack.common.js'); -+ -+ module.exports = merge(common, { -+ mode: 'production', -+ }); -``` - -In `webpack.common.js`, we now have setup our `entry` and `output` configuration and we've included any plugins that are required for both environments. In `webpack.dev.js`, we've set ``mode`` to ``development``. Also, we've added the recommended `devtool` for that environment (strong source mapping), as well as our simple `devServer` configuration. Finally, in `webpack.prod.js`,``mode`` is set to ``production`` which loads `TerserPlugin` which was first introduced by the [tree shaking](/guides/tree-shaking) guide. - -Note the use of `merge()` in the environment-specific configurations to easily include our common configuration in `dev` and `prod`. The `webpack-merge` tool offers a variety of advanced features for merging but for our use case we won't need any of that. - - -## NPM Scripts - -Now let's repoint our `scripts` to the new configurations. We'll use the _development_ one for our `webpack-dev-server`, `npm start`, script and the _production_ one for our `npm run build` script: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "src/index.js", - "scripts": { -- "start": "webpack-dev-server --open", -+ "start": "webpack-dev-server --open --config webpack.dev.js", -- "build": "webpack" -+ "build": "webpack --config webpack.prod.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.17", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "express": "^4.15.3", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "webpack-dev-middleware": "^1.12.0", - "webpack-dev-server": "^2.9.1", - "webpack-merge": "^4.1.0", - "xml-loader": "^1.2.1" - } - } -``` - -Feel free to run those scripts and see how the output changes as we continue adding to our _production_ configuration. - - -## Specify the Mode - -Many libraries will key off the `process.env.NODE_ENV` variable to determine what should be included in the library. For example, when not in _production_ some libraries may add additional logging and testing to make debugging easier. However, with `process.env.NODE_ENV === 'production'` they might drop or add significant portions of code to optimize how things run for your actual users. Since webpack v4, specifying [`mode`](/concepts/mode/) automatically configures [`DefinePlugin`](/plugins/define-plugin) for you: - -__webpack.prod.js__ - -``` diff - const merge = require('webpack-merge'); - const common = require('./webpack.common.js'); - - module.exports = merge(common, { - mode: 'production', - }); -``` - -T> Technically, `NODE_ENV` is a system environment variable that Node.js exposes into running scripts. It is used by convention to determine dev-vs-prod behavior by server tools, build scripts, and client-side libraries. Contrary to expectations, `process.env.NODE_ENV` is not set to `"production"` __within__ the build script `webpack.config.js`, see [#2537](https://github.com/webpack/webpack/issues/2537). Thus, conditionals like `process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'` within webpack configurations do not work as expected. - -If you're using a library like [`react`](https://reactjs.org/), you should actually see a significant drop in bundle size after adding this plugin. Also note that any of our local `/src` code can key off of this as well, so the following check would be valid: - -__src/index.js__ - -``` diff - import { cube } from './math.js'; -+ -+ if (process.env.NODE_ENV !== 'production') { -+ console.log('Looks like we are in development mode!'); -+ } - - function component() { - var element = document.createElement('pre'); - - element.innerHTML = [ - 'Hello webpack!', - '5 cubed is equal to ' + cube(5) - ].join('\n\n'); - - return element; - } - - document.body.appendChild(component()); -``` - - -## Minification - -webpack v4+ will minify your code by default in [`production mode`](/concepts/mode/#mode-production). - -Note that while the [`TerserPlugin`](/plugins/terser-webpack-plugin) is a great place to start for minification and being used by default, there are other options out there. Here are a few more popular ones: - -- [`BabelMinifyWebpackPlugin`](https://github.com/webpack-contrib/babel-minify-webpack-plugin) -- [`ClosureCompilerPlugin`](https://github.com/roman01la/webpack-closure-compiler) - -If you decide to try another minification plugin, just make sure your new choice also drops dead code as described in the [tree shaking](/guides/tree-shaking) guide and provide it as the [`optimization.minimizer`](/configuration/optimization/#optimization-minimizer). - - -## Source Mapping - -We encourage you to have source maps enabled in production, as they are useful for debugging as well as running benchmark tests. That said, you should choose one with a fairly quick build speed that's recommended for production use (see [`devtool`](/configuration/devtool)). For this guide, we'll use the `source-map` option in _production_ as opposed to the `inline-source-map` we used in _development_: - -__webpack.prod.js__ - -``` diff - const merge = require('webpack-merge'); - const common = require('./webpack.common.js'); - - module.exports = merge(common, { - mode: 'production', -+ devtool: 'source-map' - }); -``` - -T> Avoid `inline-***` and `eval-***` use in production as they can increase bundle size and reduce the overall performance. - - -## Minimize CSS - -It is crucial to minimize your CSS on production, please see [Minimizing for Production](/plugins/mini-css-extract-plugin/#minimizing-for-production) section. - - -## CLI Alternatives - -Some of what has been described above is also achievable via the command line. For example, the `--optimize-minimize` flag will include the `TerserPlugin` behind the scenes. The `--define process.env.NODE_ENV="'production'"` will do the same for the `DefinePlugin` instance described above. And, `webpack -p` will automatically invoke both those flags and thus the plugins to be included. - -While these short hand methods are nice, we usually recommend just using the configuration as it's better to understand exactly what is being done for you in both cases. The configuration also gives you more control on fine tuning other options within both plugins. - - -# Code Splitting - -T> This guide extends the examples provided in [Getting Started](/guides/getting-started) and [Output Management](/guides/output-management). Please make sure you are at least familiar with the examples provided in them. - -Code splitting is one of the most compelling features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel. It can be used to achieve smaller bundles and control resource load prioritization which, if used correctly, can have a major impact on load time. - -There are three general approaches to code splitting available: - -- Entry Points: Manually split code using [`entry`](/configuration/entry-context) configuration. -- Prevent Duplication: Use the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) to dedupe and split chunks. -- Dynamic Imports: Split code via inline function calls within modules. - - -## Entry Points - -This is by far the easiest, and most intuitive, way to split code. However, it is more manual and has some pitfalls we will go over. Let's take a look at how we might split another module from the main bundle: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- another-module.js -|- /node_modules -``` - -__another-module.js__ - -``` js -import _ from 'lodash'; - -console.log( - _.join(['Another', 'module', 'loaded!'], ' ') -); -``` - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - mode: 'development', - entry: { - index: './src/index.js', -+ another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -This will yield the following build result: - -``` bash -... - Asset Size Chunks Chunk Names -another.bundle.js 550 KiB another [emitted] another - index.bundle.js 550 KiB index [emitted] index -Entrypoint index = index.bundle.js -Entrypoint another = another.bundle.js -... -``` - -As mentioned there are some pitfalls to this approach: - -- If there are any duplicated modules between entry chunks they will be included in both bundles. -- It isn't as flexible and can't be used to dynamically split code with the core application logic. - -The first of these two points is definitely an issue for our example, as `lodash` is also imported within `./src/index.js` and will thus be duplicated in both bundles. Let's remove this duplication by using the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). - - -## Prevent Duplication - -The [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) allows us to extract common dependencies into an existing entry chunk or an entirely new chunk. Let's use this to de-duplicate the `lodash` dependency from the previous example: - -W> The `CommonsChunkPlugin` has been removed in webpack v4 legato. To learn how chunks are treated in the latest version, check out the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - mode: 'development', - entry: { - index: './src/index.js', - another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ optimization: { -+ splitChunks: { -+ chunks: 'all' -+ } -+ } - }; -``` - -With the [`optimization.splitChunks`](/plugins/split-chunks-plugin/#optimization-splitchunks) configuration option in place, we should now see the duplicate dependency removed from our `index.bundle.js` and `another.bundle.js`. The plugin should notice that we've separated `lodash` out to a separate chunk and remove the dead weight from our main bundle. Let's do an `npm run build` to see if it worked: - -``` bash -... - Asset Size Chunks Chunk Names - another.bundle.js 5.95 KiB another [emitted] another - index.bundle.js 5.89 KiB index [emitted] index -vendors~another~index.bundle.js 547 KiB vendors~another~index [emitted] vendors~another~index -Entrypoint index = vendors~another~index.bundle.js index.bundle.js -Entrypoint another = vendors~another~index.bundle.js another.bundle.js -... -``` - -Here are some other useful plugins and loaders provided by the community for splitting code: - -- [`mini-css-extract-plugin`](/plugins/mini-css-extract-plugin): Useful for splitting CSS out from the main application. -- [`bundle-loader`](/loaders/bundle-loader): Used to split code and lazy load the resulting bundles. -- [`promise-loader`](https://github.com/gaearon/promise-loader): Similar to the `bundle-loader` but uses promises. - - -## Dynamic Imports - -Two similar techniques are supported by webpack when it comes to dynamic code splitting. The first and recommended approach is to use the [`import()` syntax](/api/module-methods#import-) that conforms to the [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) for dynamic imports. The legacy, webpack-specific approach is to use [`require.ensure`](/api/module-methods#require-ensure). Let's try using the first of these two approaches... - -W> `import()` calls use [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -Before we start, let's remove the extra [`entry`](/concepts/entry-points/) and [`optimization.splitChunks`](/plugins/split-chunks-plugin) from our config as they won't be needed for this next demonstration: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - mode: 'development', - entry: { -+ index: './src/index.js' -- index: './src/index.js', -- another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', -+ chunkFilename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- optimization: { -- splitChunks: { -- chunks: 'all' -- } -- } - }; -``` - -Note the use of `chunkFilename`, which determines the name of non-entry chunk files. For more information on `chunkFilename`, see [output documentation](/configuration/output/#output-chunkfilename). We'll also update our project to remove the now unused files: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -- |- another-module.js -|- /node_modules -``` - -Now, instead of statically importing `lodash`, we'll use dynamic importing to separate a chunk: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -- -- function component() { -+ function getComponent() { -- var element = document.createElement('div'); -- -- // Lodash, now imported by this script -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => { -+ var element = document.createElement('div'); -+ -+ element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ -+ return element; -+ -+ }).catch(error => 'An error occurred while loading the component'); - } - -- document.body.appendChild(component()); -+ getComponent().then(component => { -+ document.body.appendChild(component); -+ }) -``` - -The reason we need `default` is since webpack 4, when importing a CommonJS module, the import will no longer resolve to the value of `module.exports`, it will instead create an artificial namespace object for the CommonJS module, for more information on the reason behind this, read [webpack 4: import() and CommonJs](https://medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655) - -Note the use of `webpackChunkName` in the comment. This will cause our separate bundle to be named `lodash.bundle.js` instead of just `[id].bundle.js`. For more information on `webpackChunkName` and the other available options, see the [`import()` documentation](/api/module-methods#import-). Let's run webpack to see `lodash` separated out to a separate bundle: - -``` bash -... - Asset Size Chunks Chunk Names - index.bundle.js 7.88 KiB index [emitted] index -vendors~lodash.bundle.js 547 KiB vendors~lodash [emitted] vendors~lodash -Entrypoint index = index.bundle.js -... -``` - -As `import()` returns a promise, it can be used with [`async` functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). However, this requires using a pre-processor like Babel and the [Syntax Dynamic Import Babel Plugin](https://babeljs.io/docs/plugins/syntax-dynamic-import/#installation). Here's how it would simplify the code: - -__src/index.js__ - -``` diff -- function getComponent() { -+ async function getComponent() { -- return import(/* webpackChunkName: "lodash" */ 'lodash').then({ default: _ } => { -- var element = document.createElement('div'); -- -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- -- return element; -- -- }).catch(error => 'An error occurred while loading the component'); -+ var element = document.createElement('div'); -+ const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash'); -+ -+ element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ -+ return element; - } - - getComponent().then(component => { - document.body.appendChild(component); - }); -``` - - -## Prefetching/Preloading modules - -webpack 4.6.0+ adds support for prefetching and preloading. - -Using these inline directives while declaring your imports allows webpack to output “Resource Hint” which tells the browser that for: - -- prefetch: resource is probably needed for some navigation in the future -- preload: resource might be needed during the current navigation - -Simple prefetch example can be having a `HomePage` component, which renders a `LoginButton` component which then on demand loads a `LoginModal` component after being clicked. - -__LoginButton.js__ - -```js -//... -import(/* webpackPrefetch: true */ 'LoginModal'); -``` - -This will result in `<link rel="prefetch" href="login-modal-chunk.js">` being appended in the head of the page, which will instruct the browser to prefetch in idle time the `login-modal-chunk.js` file. - -T> webpack will add the prefetch hint once the parent chunk has been loaded. - -Preload directive has a bunch of differences compared to prefetch: - -- A preloaded chunk starts loading in parallel to the parent chunk. A prefetched chunk starts after the parent chunk finishes loading. -- A preloaded chunk has medium priority and is instantly downloaded. A prefetched chunk is downloaded while browser is idle. -- A preloaded chunk should be instantly requested by the parent chunk. A prefetched chunk can be used anytime in the future. -- Browser support is different. - -Simple preload example can be having a `Component` which always depends on a big library that should be in a separate chunk. - -Let's imagine a component `ChartComponent` which needs huge `ChartingLibrary`. It displays a `LoadingIndicator` when rendered and instantly does an on demand import of `ChartingLibrary`: - -__ChartComponent.js__ - -```js -//... -import(/* webpackPreload: true */ 'ChartingLibrary'); -``` - -When a page which uses the `ChartComponent` is requested, the charting-library-chunk is also requested via `<link rel="preload">`. Assuming the page-chunk is smaller and finishes faster, the page will be displayed with a `LoadingIndicator`, until the already requested `charting-library-chunk` finishes. This will give a little load time boost since it only needs one round-trip instead of two. Especially in high-latency environments. - -T> Using webpackPreload incorrectly can actually hurt performance, so be careful when using it. - - -## Bundle Analysis - -Once you start splitting your code, it can be useful to analyze the output to check where modules have ended up. The [official analyze tool](https://github.com/webpack/analyse) is a good place to start. There are some other community-supported options out there as well: - -- [webpack-chart](https://alexkuz.github.io/webpack-chart/): Interactive pie chart for webpack stats. -- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/): Visualize and analyze your bundles to see which modules are taking up space and which might be duplicates. -- [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer): A plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap. -- [webpack bundle optimize helper](https://webpack.jakoblind.no/optimize): This tool will analyze your bundle and give you actionable suggestions on what to improve to reduce your bundle size. - -## Next Steps - -See [Lazy Loading](/guides/lazy-loading) for a more concrete example of how `import()` can be used in a real application and [Caching](/guides/caching) to learn how to split code more effectively. - - -# Lazy Loading - -T> This guide is a small follow-up to [Code Splitting](/guides/code-splitting). If you have not yet read through that guide, please do so now. - -Lazy, or "on demand", loading is a great way to optimize your site or application. This practice essentially involves splitting your code at logical breakpoints, and then loading it once the user has done something that requires, or will require, a new block of code. This speeds up the initial load of the application and lightens its overall weight as some blocks may never even be loaded. - - -## Example - -Let's take the example from [Code Splitting](/guides/code-splitting#dynamic-imports) and tweak it a bit to demonstrate this concept even more. The code there does cause a separate chunk, `lodash.bundle.js`, to be generated and technically "lazy-loads" it as soon as the script is run. The trouble is that no user interaction is required to load the bundle -- meaning that every time the page is loaded, the request will fire. This doesn't help us too much and will impact performance negatively. - -Let's try something different. We'll add an interaction to log some text to the console when the user clicks a button. However, we'll wait to load that code (`print.js`) until the interaction occurs for the first time. To do this we'll go back and rework the [final _Dynamic Imports_ example](/guides/code-splitting#dynamic-imports) from _Code Splitting_ and leave `lodash` in the main chunk. - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- print.js -|- /node_modules -``` - -__src/print.js__ - -``` js -console.log('The print.js module has loaded! See the network tab in dev tools...'); - -export default () => { - console.log('Button Clicked: Here\'s "some text"!'); -}; -``` - -__src/index.js__ - -``` diff -+ import _ from 'lodash'; -+ -- async function getComponent() { -+ function component() { - var element = document.createElement('div'); -- const _ = await import(/* webpackChunkName: "lodash" */ 'lodash'); -+ var button = document.createElement('button'); -+ var br = document.createElement('br'); - -+ button.innerHTML = 'Click me and look at the console!'; - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.appendChild(br); -+ element.appendChild(button); -+ -+ // Note that because a network request is involved, some indication -+ // of loading would need to be shown in a production-level site/app. -+ button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => { -+ var print = module.default; -+ -+ print(); -+ }); - - return element; - } - -- getComponent().then(component => { -- document.body.appendChild(component); -- }); -+ document.body.appendChild(component()); -``` - -W> Note that when using `import()` on ES6 modules you must reference the `.default` property as it's the actual `module` object that will be returned when the promise is resolved. - -Now let's run webpack and check out our new lazy-loading functionality: - -``` bash -... - Asset Size Chunks Chunk Names -print.bundle.js 417 bytes 0 [emitted] print -index.bundle.js 548 kB 1 [emitted] [big] index - index.html 189 bytes [emitted] -... -``` - - -## Frameworks - -Many frameworks and libraries have their own recommendations on how this should be accomplished within their methodologies. Here are a few examples: - -- React: [Code Splitting and Lazy Loading](https://reacttraining.com/react-router/web/guides/code-splitting) -- Vue: [Lazy Load in Vue using Webpack's code splitting](https://alexjoverm.github.io/2017/07/16/Lazy-load-in-Vue-using-Webpack-s-code-splitting/) -- AngularJS: [AngularJS + Webpack = lazyLoad](https://medium.com/@var_bin/angularjs-webpack-lazyload-bb7977f390dd) by [@var_bincom](https://twitter.com/var_bincom) - - -# Caching - -T> The examples in this guide stem from [getting started](/guides/getting-started), [output management](/guides/output-management) and [code splitting](/guides/code-splitting). - -So we're using webpack to bundle our modular application which yields a deployable `/dist` directory. Once the contents of `/dist` have been deployed to a server, clients (typically browsers) will hit that server to grab the site and its assets. The last step can be time consuming, which is why browsers use a technique called [caching](https://searchstorage.techtarget.com/definition/cache). This allows sites to load faster with less unnecessary network traffic, however it can also cause headaches when you need new code to be picked up. - -This guide focuses on the configuration needed to ensure files produced by webpack compilation can remain cached unless their contents has changed. - - -## Output Filenames - -A simple way to ensure the browser picks up changed files is by using `output.filename` [substitutions](/configuration/output#output-filename). The `[hash]` substitution can be used to include a build-specific hash in the filename, however it's even better to use the `[contenthash]` substitution which is the hash of the content of a file, which is different for each asset. - -Let's get our project set up using the example from [getting started](/guides/getting-started) with the `plugins` from [output management](/guides/output-management), so we don't have to deal with maintaining our `index.html` file manually: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -|- /node_modules -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ -- title: 'Output Management' -+ title: 'Caching' - }) - ], - output: { -- filename: 'bundle.js', -+ filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Running our build script, `npm run build`, with this configuration should produce the following output: - -``` bash -... - Asset Size Chunks Chunk Names -main.7e2c49a622975ebd9b7e.js 544 kB 0 [emitted] [big] main - index.html 197 bytes [emitted] -... -``` - -As you can see the bundle's name now reflects its content (via the hash). If we run another build without making any changes, we'd expect that filename to stay the same. However, if we were to run it again, we may find that this is not the case: - -``` bash -... - Asset Size Chunks Chunk Names -main.205199ab45963f6a62ec.js 544 kB 0 [emitted] [big] main - index.html 197 bytes [emitted] -... -``` - -This is because webpack includes certain boilerplate, specifically the runtime and manifest, in the entry chunk. - -W> Output may differ depending on your current webpack version. Newer versions may not have all the same issues with hashing as some older versions, but we still recommend the following steps to be safe. - -## Extracting Boilerplate - -As we learned in [code splitting](/guides/code-splitting), the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) can be used to split modules out into separate bundles. webpack provides an optimization feature which does split out runtime code into a separate chunk(s) according to the options provided, simply use [`optimization.runtimeChunk`](/configuration/optimization/#optimization-runtimechunk) set to `single` for creating one runtime bundle: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, -+ optimization: { -+ runtimeChunk: 'single' -+ } - }; -``` - -Let's run another build to see the extracted `runtime` bundle: - -``` bash -Hash: 82c9c385607b2150fab2 -Version: webpack 4.12.0 -Time: 3027ms - Asset Size Chunks Chunk Names -runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime - main.e81de2cf758ada72f306.js 69.5 KiB 1 [emitted] main - index.html 275 bytes [emitted] -[1] (webpack)/buildin/module.js 497 bytes {1} [built] -[2] (webpack)/buildin/global.js 489 bytes {1} [built] -[3] ./src/index.js 309 bytes {1} [built] - + 1 hidden module -``` - -It's also good practice to extract third-party libraries, such as `lodash` or `react`, to a separate `vendor` chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date. -This can be done by using the [`cacheGroups`](/plugins/split-chunks-plugin/#splitchunks-cachegroups) option of the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) demonstrated in [Example 2 of SplitChunksPlugin](/plugins/split-chunks-plugin/#split-chunks-example-2). Lets add `optimization.splitChunks` with `cacheGroups` with next params and build: - -__webpack.config.js__ - -``` diff - var path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - }), - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, - optimization: { -- runtimeChunk: 'single' -+ runtimeChunk: 'single', -+ splitChunks: { -+ cacheGroups: { -+ vendor: { -+ test: /[\\/]node_modules[\\/]/, -+ name: 'vendors', -+ chunks: 'all' -+ } -+ } -+ } - } - }; -``` - -Let's run another build to see our new `vendor` bundle: - -``` bash -... - Asset Size Chunks Chunk Names -runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime -vendors.a42c3ca0d742766d7a28.js 69.4 KiB 1 [emitted] vendors - main.abf44fedb7d11d4312d7.js 240 bytes 2 [emitted] main - index.html 353 bytes [emitted] -... -``` - -We can now see that our `main` bundle does not contain `vendor` code from `node_modules` directory and is down in size to `240 bytes`! - -## Module Identifiers - -Let's add another module, `print.js`, to our project: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- print.js -|- /node_modules -``` - -__print.js__ - -``` diff -+ export default function print(text) { -+ console.log(text); -+ }; -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import Print from './print'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.onclick = Print.bind(null, 'Hello webpack!'); - - return element; - } - - document.body.appendChild(component()); -``` - -Running another build, we would expect only our `main` bundle's hash to change, however... - -``` bash -... - Asset Size Chunks Chunk Names - vendor.a7561fb0e9a071baadb9.js 541 kB 0 [emitted] [big] vendor - main.b746e3eb72875af2caa9.js 1.22 kB 1 [emitted] main -manifest.1400d5af64fc1b7b3a45.js 5.85 kB 2 [emitted] manifest - index.html 352 bytes [emitted] -... -``` - -... we can see that all three have. This is because each [`module.id`](/api/module-variables#module-id-commonjs-) is incremented based on resolving order by default. Meaning when the order of resolving is changed, the IDs will be changed as well. So, to recap: - -- The `main` bundle changed because of its new content. -- The `vendor` bundle changed because its `module.id` was changed. -- And, the `manifest` bundle changed because it now contains a reference to a new module. - -The first and last are expected -- it's the `vendor` hash we want to fix. Luckily, there are two plugins we can use to resolve this issue. The first is the `NamedModulesPlugin`, which will use the path to the module rather than a numerical identifier. While this plugin is useful during development for more readable output, it does take a bit longer to run. The second option is the [`HashedModuleIdsPlugin`](/plugins/hashed-module-ids-plugin), which is recommended for production builds: - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const webpack = require('webpack'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - }), -+ new webpack.HashedModuleIdsPlugin() - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, - optimization: { - runtimeChunk: 'single', - splitChunks: { - cacheGroups: { - vendor: { - test: /[\\/]node_modules[\\/]/, - name: 'vendors', - chunks: 'all' - } - } - } - } - }; -``` - -Now, despite any new local dependencies, our `vendor` hash should stay consistent between builds: - -``` bash -... - Asset Size Chunks Chunk Names - main.216e852f60c8829c2289.js 340 bytes 0 [emitted] main -vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors -runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime - index.html 353 bytes [emitted] -Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.216e852f60c8829c2289.js -... -``` - -And let's modify our `src/index.js` to temporarily remove that extra dependency: - -__src/index.js__ - -``` diff - import _ from 'lodash'; -- import Print from './print'; -+ // import Print from './print'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- element.onclick = Print.bind(null, 'Hello webpack!'); -+ // element.onclick = Print.bind(null, 'Hello webpack!'); - - return element; - } - - document.body.appendChild(component()); -``` - -And finally run our build again: - -``` bash -... - Asset Size Chunks Chunk Names - main.ad717f2466ce655fff5c.js 274 bytes 0 [emitted] main -vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors -runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime - index.html 353 bytes [emitted] -Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.ad717f2466ce655fff5c.js -... -``` - -We can see that both builds yielded `55e79e5927a639d21a1b` in the `vendor` bundle's filename. - - -## Conclusion - -Caching gets messy. Plain and simple. However the walk-through above should give you a running start to deploying consistent, cacheable assets. See the _Further Reading_ section below to learn more. - - -# Authoring Libraries - -Aside from applications, webpack can also be used to bundle JavaScript libraries. The following guide is meant for library authors looking to streamline their bundling strategy. - - -## Authoring a Library - -Let's assume that you are writing a small library ,`webpack-numbers`, that allows users to convert the numbers 1 through 5 from their numeric representation to a textual one and vice-versa, e.g. 2 to 'two'. - -The basic project structure may look like this: - -__project__ - -``` diff -+ |- webpack.config.js -+ |- package.json -+ |- /src -+ |- index.js -+ |- ref.json -``` - -Initialize npm, install webpack and lodash: - -``` bash -npm init -y -npm install --save-dev webpack lodash -``` - -__src/ref.json__ - -```json -[ - { - "num": 1, - "word": "One" - }, - { - "num": 2, - "word": "Two" - }, - { - "num": 3, - "word": "Three" - }, - { - "num": 4, - "word": "Four" - }, - { - "num": 5, - "word": "Five" - }, - { - "num": 0, - "word": "Zero" - } -] -``` - -__src/index.js__ - -``` js -import _ from 'lodash'; -import numRef from './ref.json'; - -export function numToWord(num) { - return _.reduce(numRef, (accum, ref) => { - return ref.num === num ? ref.word : accum; - }, ''); -} - -export function wordToNum(word) { - return _.reduce(numRef, (accum, ref) => { - return ref.word === word && word.toLowerCase() ? ref.num : accum; - }, -1); -} -``` - -The usage specification for the library use will be as follows: - -- __ES2015 module import:__ - -``` js -import * as webpackNumbers from 'webpack-numbers'; -// ... -webpackNumbers.wordToNum('Two'); -``` - -- __CommonJS module require:__ - -``` js -var webpackNumbers = require('webpack-numbers'); -// ... -webpackNumbers.wordToNum('Two'); -``` - -- __AMD module require:__ - -``` js -require(['webpackNumbers'], function ( webpackNumbers) { - // ... - webpackNumbers.wordToNum('Two'); -}); -``` - -The consumer also can use the library by loading it via a script tag: - -``` html -<!doctype html> -<html> - ... - <script src="https://unpkg.com/webpack-numbers"></script> - <script> - // ... - // Global variable - webpackNumbers.wordToNum('Five') - // Property in the window object - window.webpackNumbers.wordToNum('Five') - // ... - </script> -</html> -``` - -Note that we can also configure it to expose the library in the following ways: - -- Property in the global object, for node. -- Property in the `this` object. - -For full library configuration and code please refer to [webpack-library-example](https://github.com/kalcifer/webpack-library-example). - - -## Base Configuration - -Now let's bundle this library in a way that will achieve the following goals: - -- Using `externals` to avoid bundling `lodash`, so the consumer is required to load it. -- Setting the library name as `webpack-numbers`. -- Exposing the library as a variable called `webpackNumbers`. -- Being able to access the library inside Node.js. - -Also, the consumer should be able to access the library the following ways: - -- ES2015 module. i.e. `import webpackNumbers from 'webpack-numbers'`. -- CommonJS module. i.e. `require('webpack-numbers')`. -- Global variable when included through `script` tag. - -We can start with this basic webpack configuration: - -__webpack.config.js__ - -``` js -var path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js' - } -}; -``` - - -## Externalize Lodash - -Now, if you run `webpack`, you will find that a largish bundle is created. If you inspect the file, you'll see that lodash has been bundled along with your code. In this case, we'd prefer to treat `lodash` as a `peerDependency`. Meaning that the consumer should already have `lodash` installed. Hence you would want to give up control of this external library to the consumer of your library. - -This can be done using the `externals` configuration: - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js' -- } -+ }, -+ externals: { -+ lodash: { -+ commonjs: 'lodash', -+ commonjs2: 'lodash', -+ amd: 'lodash', -+ root: '_' -+ } -+ } - }; -``` - -This means that your library expects a dependency named `lodash` to be available in the consumer's environment. - -T> Note that if you only plan on using your library as a dependency in another webpack bundle, you may specify `externals` as an array. - - -## External Limitations - -For libraries that use several files from a dependency: - -``` js -import A from 'library/one'; -import B from 'library/two'; - -// ... -``` - -You won't be able to exclude them from bundle by specifying `library` in the externals. You'll either need to exclude them one by one or by using a regular expression. - -``` js -module.exports = { - //... - externals: [ - 'library/one', - 'library/two', - // Everything that starts with "library/" - /^library\/.+$/ - ] -}; -``` - - -## Expose the Library - -For widespread use of the library, we would like it to be compatible in different environments, i.e. CommonJS, AMD, Node.js and as a global variable. To make your library available for consumption, add the `library` property inside `output`: - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), -- filename: 'webpack-numbers.js' -+ filename: 'webpack-numbers.js', -+ library: 'webpackNumbers' - }, - externals: { - lodash: { - commonjs: 'lodash', - commonjs2: 'lodash', - amd: 'lodash', - root: '_' - } - } - }; -``` - -T> Note that the `library` setup is tied to the `entry` configuration. For most libraries, specifying a single entry point is sufficient. While [multi-part libraries](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) are possible, it is simpler to expose partial exports through an [index script](https://stackoverflow.com/questions/34072598/es6-exporting-importing-in-index-file) that serves as a single entry point. Using an `array` as an `entry` point for a library is __not recommended__. - -This exposes your library bundle available as a global variable named `webpackNumbers` when imported. To make the library compatible with other environments, add `libraryTarget` property to the config. This will add the different options about how the library can be exposed. - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js', -- library: 'webpackNumbers' -+ library: 'webpackNumbers', -+ libraryTarget: 'umd' - }, - externals: { - lodash: { - commonjs: 'lodash', - commonjs2: 'lodash', - amd: 'lodash', - root: '_' - } - } - }; -``` - -You can expose the library in the following ways: - -- Variable: as a global variable made available by a `script` tag (`libraryTarget:'var'`). -- This: available through the `this` object (`libraryTarget:'this'`). -- Window: available trough the `window` object, in the browser (`libraryTarget:'window'`). -- UMD: available after AMD or CommonJS `require` (`libraryTarget:'umd'`). - -If `library` is set and `libraryTarget` is not, `libraryTarget` defaults to `var` as specified in the [output configuration documentation](/configuration/output). See [`output.libraryTarget`](/configuration/output#output-librarytarget) there for a detailed list of all available options. - -W> With webpack 3.5.5, using `libraryTarget: { root:'_' }` doesn't work properly (as stated in [issue 4824](https://github.com/webpack/webpack/issues/4824)). However, you can set `libraryTarget: { var: '_' }` to expect the library as a global variable. - - -### Final Steps - -Optimize your output for production by following the steps in the [production guide](/guides/production). Let's also add the path to your generated bundle as the package's `main` field in with our `package.json` - -__package.json__ - -``` json -{ - ... - "main": "dist/webpack-numbers.js", - ... -} -``` - -Or, to add as standard module as per [this guide](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage): - -``` json -{ - ... - "module": "src/index.js", - ... -} -``` - -The key `main` refers to the [standard from `package.json`](https://docs.npmjs.com/files/package.json#main), and `module` to [a](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md) [proposal](https://github.com/rollup/rollup/wiki/pkg.module) to allow the JavaScript ecosystem upgrade to use ES2015 modules without breaking backwards compatibility. - -W> The `module` property should point to a script that utilizes ES2015 module syntax but no other syntax features that aren't yet supported by browsers or node. This enables webpack to parse the module syntax itself, allowing for lighter bundles via [tree shaking](https://webpack.js.org/guides/tree-shaking/) if users are only consuming certain parts of the library. - -Now you can [publish it as an npm package](https://docs.npmjs.com/getting-started/publishing-npm-packages) and find it at [unpkg.com](https://unpkg.com/#/) to distribute it to your users. - -T> To expose stylesheets associated with your library, the [`ExtractTextPlugin`](/plugins/extract-text-webpack-plugin) should be used. Users can then consume and load these as they would any other stylesheet. - - -# Shimming - -The `webpack` compiler can understand modules written as ES2015 modules, CommonJS or AMD. However, some third party libraries may expect global dependencies (e.g. `$` for `jQuery`). The libraries might also create globals which need to be exported. These "broken modules" are one instance where _shimming_ comes into play. - -W> __We don't recommend using globals!__ The whole concept behind webpack is to allow more modular front-end development. This means writing isolated modules that are well contained and do not rely on hidden dependencies (e.g. globals). Please use these features only when necessary. - -Another instance where _shimming_ can be useful is when you want to [polyfill](https://en.wikipedia.org/wiki/Polyfill) browser functionality to support more users. In this case, you may only want to deliver those polyfills to the browsers that need patching (i.e. load them on demand). - -The following article will walk through both of these use cases. - -T> For simplicity, this guide stems from the examples in [Getting Started](/guides/getting-started). Please make sure you are familiar with the setup there before moving on. - - -## Shimming Globals - -Let's start with the first use case of shimming global variables. Before we do anything let's take another look at our project: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -|- /node_modules -``` - -Remember that `lodash` package we were using? For demonstration purposes, let's say we wanted to instead provide this as a global throughout our application. To do this, we can use the `ProvidePlugin`. - -The [`ProvidePlugin`](/plugins/provide-plugin) makes a package available as a variable in every module compiled through webpack. If webpack sees that variable used, it will include the given package in the final bundle. Let's go ahead by removing the `import` statement for `lodash` and instead providing it via the plugin: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -- - function component() { - var element = document.createElement('div'); - -- // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') -- } -+ }, -+ plugins: [ -+ new webpack.ProvidePlugin({ -+ _: 'lodash' -+ }) -+ ] - }; -``` - -What we've essentially done here is tell webpack... - -> If you encounter at least one instance of the variable `_`, include the `lodash` package and provide it to the modules that need it. - -If we run a build, we should still see the same output: - -``` bash -... - Asset Size Chunks Chunk Names -bundle.js 544 kB 0 [emitted] [big] main -... -``` - -We can also use the `ProvidePlugin` to expose a single export of a module by configuring it with an "array path" (e.g. `[module, child, ...children?]`). So let's imagine we only wanted to provide the `join` method from `lodash` wherever it's invoked: - -__src/index.js__ - -``` diff - function component() { - var element = document.createElement('div'); - -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - plugins: [ - new webpack.ProvidePlugin({ -- _: 'lodash' -+ join: ['lodash', 'join'] - }) - ] - }; -``` - -This would go nicely with [Tree Shaking](/guides/tree-shaking) as the rest of the `lodash` library should get dropped. - - -## Granular Shimming - -Some legacy modules rely on `this` being the `window` object. Let's update our `index.js` so this is the case: - -``` diff - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); -+ -+ // Assume we are in the context of `window` -+ this.alert('Hmmm, this probably isn\'t a great idea...') - - return element; - } - - document.body.appendChild(component()); -``` - -This becomes a problem when the module is executed in a CommonJS context where `this` is equal to `module.exports`. In this case you can override `this` using the [`imports-loader`](/loaders/imports-loader/): - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ module: { -+ rules: [ -+ { -+ test: require.resolve('index.js'), -+ use: 'imports-loader?this=>window' -+ } -+ ] -+ }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - - -## Global Exports - -Let's say a library creates a global variable that it expects its consumers to use. We can add a small module to our setup to demonstrate this: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js -+ |- globals.js - |- /node_modules -``` - -__src/globals.js__ - -``` js -var file = 'blah.txt'; -var helpers = { - test: function() { console.log('test something'); }, - parse: function() { console.log('parse something'); } -}; -``` - -Now, while you'd likely never do this in your own source code, you may encounter a dated library you'd like to use that contains similar code to what's shown above. In this case, we can use [`exports-loader`](/loaders/exports-loader/), to export that global variable as a normal module export. For instance, in order to export `file` as `file` and `helpers.parse` as `parse`: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: require.resolve('index.js'), - use: 'imports-loader?this=>window' -- } -+ }, -+ { -+ test: require.resolve('globals.js'), -+ use: 'exports-loader?file,parse=helpers.parse' -+ } - ] - }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - -Now from within our entry script (i.e. `src/index.js`), we could `import { file, parse } from './globals.js';` and all should work smoothly. - - -## Loading Polyfills - -Almost everything we've discussed thus far has been in relation to handling legacy packages. Let's move on to our second topic: __polyfills__. - -There's a lot of ways to load polyfills. For example, to include the [`babel-polyfill`](https://babeljs.io/docs/usage/polyfill/) we might simply: - -``` bash -npm install --save babel-polyfill -``` - -and `import` it so as to include it in our main bundle: - -__src/index.js__ - -``` diff -+ import 'babel-polyfill'; -+ - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -T> Note that we aren't binding the `import` to a variable. This is because polyfills simply run on their own, prior to the rest of the code base, allowing us to then assume certain native functionality exists. - -Now while this is one approach, __including polyfills in the main bundle is not recommended__ because this penalizes modern browsers users by making them download a bigger file with unneeded scripts. - -Let's move our `import` to a new file and add the [`whatwg-fetch`](https://github.com/github/fetch) polyfill: - -``` bash -npm install --save whatwg-fetch -``` - -__src/index.js__ - -``` diff -- import 'babel-polyfill'; -- - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js - |- globals.js -+ |- polyfills.js - |- /node_modules -``` - -__src/polyfills.js__ - -```javascript -import 'babel-polyfill'; -import 'whatwg-fetch'; -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { -- entry: './src/index.js', -+ entry: { -+ polyfills: './src/polyfills.js', -+ index: './src/index.js' -+ }, - output: { -- filename: 'bundle.js', -+ filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: require.resolve('index.js'), - use: 'imports-loader?this=>window' - }, - { - test: require.resolve('globals.js'), - use: 'exports-loader?file,parse=helpers.parse' - } - ] - }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - -With that in place, we can add the logic to conditionally load our new `polyfills.bundle.js` file. How you make this decision depends on the technologies and browsers you need to support. We'll just do some simple testing to determine whether our polyfills are needed: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> - <title>Getting Started</title> -+ <script> -+ var modernBrowser = ( -+ 'fetch' in window && -+ 'assign' in Object -+ ); -+ -+ if ( !modernBrowser ) { -+ var scriptElement = document.createElement('script'); -+ -+ scriptElement.async = false; -+ scriptElement.src = '/polyfills.bundle.js'; -+ document.head.appendChild(scriptElement); -+ } -+ </script> - </head> - <body> - <script src="index.bundle.js"></script> - </body> - </html> -``` - -Now we can `fetch` some data within our entry script: - -__src/index.js__ - -``` diff - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -+ -+ fetch('https://jsonplaceholder.typicode.com/users') -+ .then(response => response.json()) -+ .then(json => { -+ console.log('We retrieved some data! AND we\'re confident it will work on a variety of browser distributions.') -+ console.log(json) -+ }) -+ .catch(error => console.error('Something went wrong when fetching this data: ', error)) -``` - -If we run our build, another `polyfills.bundle.js` file will be emitted and everything should still run smoothly in the browser. Note that this set up could likely be improved upon but it should give you a good idea of how you can provide polyfills only to the users that actually need them. - - -## Further Optimizations - -The `babel-preset-env` package uses [browserslist](https://github.com/browserslist/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the [`useBuiltIns`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins) option, `false` by default, which converts your global `babel-polyfill` import to a more granular feature by feature `import` pattern: - -``` js -import 'core-js/modules/es7.string.pad-start'; -import 'core-js/modules/es7.string.pad-end'; -import 'core-js/modules/web.timers'; -import 'core-js/modules/web.immediate'; -import 'core-js/modules/web.dom.iterable'; -``` - -See [the repository](https://github.com/babel/babel-preset-env) for more information. - - -## Node Built-Ins - -Node built-ins, like `process`, can be polyfilled right directly from your configuration file without the use of any special loaders or plugins. See the [node configuration page](/configuration/node) for more information and examples. - - -## Other Utilities - -There are a few other tools that can help when dealing with legacy modules. - -The [`script-loader`](/loaders/script-loader/) evaluates code in the global context, similar to inclusion via a `script` tag. In this mode, every normal library should work. `require`, `module`, etc. are undefined. - -W> When using the `script-loader`, the module is added as a string to the bundle. It is not minimized by `webpack`, so use a minimized version. There is also no `devtool` support for libraries added by this loader. - -When there is no AMD/CommonJS version of the module and you want to include the `dist`, you can flag this module in [`noParse`](/configuration/module/#module-noparse). This will cause webpack to include the module without parsing it or resolving `require()` and `import` statements. This practice is also used to improve the build performance. - -W> Any feature requiring the AST, like the `ProvidePlugin`, will not work. - -Lastly, there are some modules that support multiple [module styles](/concepts/modules); e.g. a combination of AMD, CommonJS, and legacy. In most of these cases, they first check for `define` and then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by setting `define=>false` via the [`imports-loader`](/loaders/imports-loader/). - - -# Progressive Web Application - -T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. - -Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications. There are many things that can contribute to that. Of these, the most significant is the ability for an app to be able to function when __offline__. This is achieved through the use of a web technology called [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers/). - -This section will focus on adding an offline experience to our app. We'll achieve this using a Google project called [Workbox](https://github.com/GoogleChrome/workbox) which provides tools that help make offline support for web apps easier to setup. - - -## We Don't Work Offline Now - -So far, we've been viewing the output by going directly to the local file system. Typically though, a real user accesses a web app over a network; their browser talking to a __server__ which will serve up the required assets (e.g. `.html`, `.js`, and `.css` files). - -So let's test what the current experience is like using a simple server. Let's use the [http-server](https://www.npmjs.com/package/http-server) package: `npm install http-server --save-dev`. We'll also amend the `scripts` section of our `package.json` to add in a `start` script: - -__package.json__ - -``` diff -{ - ... - "scripts": { -- "build": "webpack" -+ "build": "webpack", -+ "start": "http-server dist" - }, - ... -} -``` - -If you haven't previously done so, run the command `npm run build` to build your project. Then run the command `npm start`. This should produce the following output: - -``` bash -> http-server dist - -Starting up http-server, serving dist -Available on: - http://xx.x.x.x:8080 - http://127.0.0.1:8080 - http://xxx.xxx.x.x:8080 -Hit CTRL-C to stop the server -``` - -If you open your browser to `http://localhost:8080` (i.e. `http://127.0.0.1`) you should see your webpack application being served from the `dist` directory. If you stop the server and refresh, the webpack application is no longer available. - -This is what we aim to change. Once we reach the end of this module we should be able to stop the server, hit refresh and still see our application. - - -## Adding Workbox - -Let's add the Workbox webpack plugin and adjust the `webpack.config.js` file: - -``` bash -npm install workbox-webpack-plugin --save-dev -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const WorkboxPlugin = require('workbox-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ -- title: 'Output Management' -+ title: 'Progressive Web Application' -- }) -+ }), -+ new WorkboxPlugin.GenerateSW({ -+ // these options encourage the ServiceWorkers to get in there fast -+ // and not allow any straggling "old" SWs to hang around -+ clientsClaim: true, -+ skipWaiting: true -+ }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -With that in place, let's see what happens when we do an `npm run build`: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 545 kB 0, 1 [emitted] [big] app - print.bundle.js 2.74 kB 1 [emitted] print - index.html 254 bytes [emitted] -precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 268 bytes [emitted] - service-worker.js 1 kB [emitted] -... -``` - -As you can see, we now have 2 extra files being generated; `service-worker.js` and the more verbose `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js`. `service-worker.js` is the Service Worker file and `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js` is a file that `service-worker.js` requires so it can run. Your own generated files will likely be different; but you should have an `service-worker.js` file there. - -So we're now at the happy point of having produced a Service Worker. What's next? - - -## Registering Our Service Worker - -Let's allow our Service Worker to come out and play by registering it. We'll do that by adding the registration code below: - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - -+ if ('serviceWorker' in navigator) { -+ window.addEventListener('load', () => { -+ navigator.serviceWorker.register('/service-worker.js').then(registration => { -+ console.log('SW registered: ', registration); -+ }).catch(registrationError => { -+ console.log('SW registration failed: ', registrationError); -+ }); -+ }); -+ } -``` - -Once more `npm run build` to build a version of the app including the registration code. Then serve it with `npm start`. Navigate to `http://localhost:8080` and take a look at the console. Somewhere in there you should see: - -``` bash -SW registered -``` - -Now to test it. Stop your server and refresh your page. If your browser supports Service Workers then you should still be looking at your application. However, it has been served up by your Service Worker and __not__ by the server. - - -## Conclusion - -You have built an offline app using the Workbox project. You've started the journey of turning your web app into a PWA. You may now want to think about taking things further. A good resource to help you with that can be found [here](https://developers.google.com/web/progressive-web-apps/). - - -# TypeScript - -T> This guide stems from the [_Getting Started_](/guides/getting-started/) guide. - -[TypeScript](https://www.typescriptlang.org) is a typed superset of JavaScript that compiles to plain JavaScript. In this guide we will learn how to integrate TypeScript with webpack. - - -## Basic Setup - -First install the TypeScript compiler and loader by running: - -``` bash -npm install --save-dev typescript ts-loader -``` - -Now we'll modify the directory structure & the configuration files: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- tsconfig.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src - |- index.js -+ |- index.ts - |- /node_modules -``` - -__tsconfig.json__ - -Let's set up a simple configuration to support JSX and compile TypeScript down to ES5... - -``` json -{ - "compilerOptions": { - "outDir": "./dist/", - "noImplicitAny": true, - "module": "es6", - "target": "es5", - "jsx": "react", - "allowJs": true - } -} -``` - -See [TypeScript's documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) to learn more about `tsconfig.json` configuration options. - -To learn more about webpack configuration, see the [configuration concepts](/concepts/configuration/). - -Now let's configure webpack to handle TypeScript: - -__webpack.config.js__ - -``` js -const path = require('path'); - -module.exports = { - entry: './src/index.ts', - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: [ '.tsx', '.ts', '.js' ] - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -This will direct webpack to _enter_ through `./index.ts`, _load_ all `.ts` and `.tsx` files through the `ts-loader`, and _output_ a `bundle.js` file in our current directory. - - -## Loader - -[`ts-loader`](https://github.com/TypeStrong/ts-loader) - -We use `ts-loader` in this guide as it makes enabling additional webpack features, such as importing other web assets, a bit easier. - - -## Source Maps - -To learn more about source maps, see the [development guide](/guides/development). - -To enable source maps, we must configure TypeScript to output inline source maps to our compiled JavaScript files. The following line must be added to our TypeScript configuration: - -__tsconfig.json__ - -``` diff - { - "compilerOptions": { - "outDir": "./dist/", -+ "sourceMap": true, - "noImplicitAny": true, - "module": "commonjs", - "target": "es5", - "jsx": "react", - "allowJs": true - } - } -``` - -Now we need to tell webpack to extract these source maps and include in our final bundle: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.ts', -+ devtool: 'inline-source-map', - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: [ '.tsx', '.ts', '.js' ] - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -See the [devtool documentation](/configuration/devtool/) for more information. - - -## Using Third Party Libraries - -When installing third party libraries from npm, it is important to remember to install the typing definition for that library. These definitions can be found at [TypeSearch](http://microsoft.github.io/TypeSearch/). - -For example if we want to install lodash we can run the following command to get the typings for it: - -``` bash -npm install --save-dev @types/lodash -``` - -For more information see [this blog post](https://blogs.msdn.microsoft.com/typescript/2016/06/15/the-future-of-declaration-files/). - - -## Importing Other Assets - -To use non-code assets with TypeScript, we need to defer the type for these imports. This requires a `custom.d.ts` file which signifies custom definitions for TypeScript in our project. Let's set up a declaration for `.svg` files: - -__custom.d.ts__ - -```typescript -declare module "*.svg" { - const content: any; - export default content; -} -``` - -Here we declare a new module for SVGs by specifying any import that ends in `.svg` and defining the module's `content` as `any`. We could be more explicit about it being a url by defining the type as string. The same concept applies to other assets including CSS, SCSS, JSON and more. - - -## Build Performance - -W> This may degrade build performance. - -See the [Build Performance](/guides/build-performance/) guide on build tooling. - - -# Environment Variables - -To disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production) you may use environment variables. - -The webpack command line [environment option](/api/cli/#environment-options) `--env` allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your `webpack.config.js`. For example, `--env.production` or `--env.NODE_ENV=local` (`NODE_ENV` is conventionally used to define the environment type, see [here](https://dzone.com/articles/what-you-should-know-about-node-env).) - -```bash -webpack --env.NODE_ENV=local --env.production --progress -``` - -T> Setting up your `env` variable without assignment, `--env.production` sets `--env.production` to `true` by default. There are also other syntaxes that you can use. See the [webpack CLI](/api/cli/#environment-options) documentation for more information. - -There is one change that you will have to make to your webpack config. Typically, `module.exports` points to the configuration object. To use the `env` variable, you must convert `module.exports` to a function: - -__webpack.config.js__ - -``` js -const path = require('path'); - -module.exports = env => { - // Use env.<YOUR VARIABLE> here: - console.log('NODE_ENV: ', env.NODE_ENV); // 'local' - console.log('Production: ', env.production); // true - - return { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -}; -``` - - -# Build Performance - -This guide contains some useful tips for improving build/compilation performance. - ---- - -## General - -The following best practices should help, whether you're running build scripts in [development](/guides/development) or [production](/guides/production). - - -### Stay Up to Date - -Use the latest webpack version. We are always making performance improvements. The latest stable version of webpack is: - -[](https://github.com/webpack/webpack/releases) - -Staying up-to-date with __Node.js__ can also help with performance. On top of this, keeping your package manager (e.g. `npm` or `yarn`) up-to-date can also help. Newer versions create more efficient module trees and increase resolving speed. - - -### Loaders - -Apply loaders to the minimal number of modules necessary. Instead of: - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - loader: 'babel-loader' - } - ] - } -}; -``` - -Use the `include` field to only apply the loader modules that actually need to be transformed by it: - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - include: path.resolve(__dirname, 'src'), - loader: 'babel-loader' - } - ] - } -}; -``` - - -### Bootstrap - -Each additional loader/plugin has a bootup time. Try to use as few tools as possible. - - -### Resolving - -The following steps can increase resolving speed: - -- Minimize the number of items in `resolve.modules`, `resolve.extensions`, `resolve.mainFiles`, `resolve.descriptionFiles`, as they increase the number of filesystem calls. -- Set `resolve.symlinks: false` if you don't use symlinks (e.g. `npm link` or `yarn link`). -- Set `resolve.cacheWithContext: false` if you use custom resolving plugins, that are not context specific. - - -### Dlls - -Use the `DllPlugin` to move code that is changed less often into a separate compilation. This will improve the application's compilation speed, although it does increase complexity of the build process. - - -### Smaller = Faster - -Decrease the total size of the compilation to increase build performance. Try to keep chunks small. - -- Use fewer/smaller libraries. -- Use the `CommonsChunkPlugin` in Multi-Page Applications. -- Use the `CommonsChunkPlugin` in `async` mode in Multi-Page Applications. -- Remove unused code. -- Only compile the part of the code you are currently developing on. - - -### Worker Pool - -The `thread-loader` can be used to offload expensive loaders to a worker pool. - -W> Don't use too many workers, as there is a boot overhead for the Node.js runtime and the loader. Minimize the module transfers between worker and main process. IPC is expensive. - - -### Persistent cache - -Enable persistent caching with the `cache-loader`. Clear cache directory on `"postinstall"` in `package.json`. - - -### Custom plugins/loaders - -Profile them to not introduce a performance problem here. - ---- - - -## Development - -The following steps are especially useful in _development_. - - -### Incremental Builds - -Use webpack's watch mode. Don't use other tools to watch your files and invoke webpack. The built-in watch mode will keep track of timestamps and passes this information to the compilation for cache invalidation. - -In some setups, watching falls back to polling mode. With many watched files, this can cause a lot of CPU load. In these cases, you can increase the polling interval with `watchOptions.poll`. - - -### Compile in Memory - -The following utilities improve performance by compiling and serving assets in memory rather than writing to disk: - -- `webpack-dev-server` -- `webpack-hot-middleware` -- `webpack-dev-middleware` - -### stats.toJson speed - -webpack 4 outputs a large amount of data with its `stats.toJson()` by default. Avoid retrieving portions of the `stats` object unless necessary in the incremental step. `webpack-dev-server` after v3.1.3 contained a substantial performance fix to minimize the amount of data retrieved from the `stats` object per incremental build step. - -### Devtool - -Be aware of the performance differences of the different `devtool` settings. - -- `"eval"` has the best performance, but doesn't assist you for transpiled code. -- The `cheap-source-map` variants are more performant, if you can live with the slightly worse mapping quality. -- Use a `eval-source-map` variant for incremental builds. - -=> In most cases, `cheap-module-eval-source-map` is the best option. - - -### Avoid Production Specific Tooling - -Certain utilities, plugins, and loaders only make sense when building for production. For example, it usually doesn't make sense to minify and mangle your code with the `TerserPlugin` while in development. These tools should typically be excluded in development: - -- `TerserPlugin` -- `ExtractTextPlugin` -- `[hash]`/`[chunkhash]` -- `AggressiveSplittingPlugin` -- `AggressiveMergingPlugin` -- `ModuleConcatenationPlugin` - - -### Minimal Entry Chunk - -webpack only emits updated chunks to the filesystem. For some configuration options, (HMR, `[name]`/`[chunkhash]` in `output.chunkFilename`, `[hash]`) the entry chunk is invalidated in addition to the changed chunks. - -Make sure the entry chunk is cheap to emit by keeping it small. The following code block extracts a chunk containing only the runtime with _all other chunks as children_: - -```js -new CommonsChunkPlugin({ - name: 'manifest', - minChunks: Infinity -}); -``` - -### Avoid Extra Optimization Steps - -webpack does extra algorithmic work to optimize the output for size and load performance. These optimizations are performant for smaller codebases, but can be costly in larger ones: - -```js -module.exports = { - // ... - optimization: { - removeAvailableModules: false, - removeEmptyChunks: false, - splitChunks: false, - } -}; -``` - -### Output Without Path Info - -webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Turn this off in the `options.output.pathinfo` setting: - -```js -module.exports = { - // ... - output: { - pathinfo: false - } -}; -``` - -### Node.js Version - -There has been a [performance regression](https://github.com/nodejs/node/issues/19769) in the latest stable versions of Node.js and its ES2015 `Map` and `Set` implementations. A fix has been merged into master, but a release has yet to be made. In the meantime, to get the most out of incremental build speeds, try to stick with version 8.9.x (the problem exists between 8.9.10 - 9.11.1). webpack has moved to using those ES2015 data structures liberally, and it will improve the initial build times as well. - -### TypeScript Loader - -Recently, `ts-loader` has started to consume the internal TypeScript watch mode APIs which dramatically decreases the number of modules to be rebuilt on each iteration. This `experimentalWatchApi` shares the same logic as the normal TypeScript watch mode itself and is quite stable for development use. Turn on `transpileOnly`, as well, for even faster incremental builds. - -```js -module.exports = { - // ... - test: /\.tsx?$/, - use: [ - { - loader: 'ts-loader', - options: { - transpileOnly: true, - experimentalWatchApi: true, - }, - }, - ], -}; -``` - -Note: the `ts-loader` documentation suggests the use of `cache-loader`, but this actually slows the incremental builds down with disk writes. - -To gain typechecking again, use the [`ForkTsCheckerWebpackPlugin`](https://www.npmjs.com/package/fork-ts-checker-webpack-plugin). - -There is a [full example](https://github.com/TypeStrong/ts-loader/tree/master/examples/fast-incremental-builds) on the ts-loader github repository. - ---- - - -## Production - -The following steps are especially useful in _production_. - -W> __Don't sacrifice the quality of your application for small performance gains!__ Keep in mind that optimization quality is, in most cases, more important than build performance. - - -### Multiple Compilations - -When using multiple compilations, the following tools can help: - -- [`parallel-webpack`](https://github.com/trivago/parallel-webpack): It allows for compilation in a worker pool. -- `cache-loader`: The cache can be shared between multiple compilations. - - -### Source Maps - -Source maps are really expensive. Do you really need them? - ---- - - -## Specific Tooling Issues - -The following tools have certain problems that can degrade build performance: - - -### Babel - -- Minimize the number of preset/plugins - - -### TypeScript - -- Use the `fork-ts-checker-webpack-plugin` for typechecking in a separate process. -- Configure loaders to skip typechecking. -- Use the `ts-loader` in `happyPackMode: true` / `transpileOnly: true`. - - -### Sass - -- `node-sass` has a bug which blocks threads from the Node.js thread pool. When using it with the `thread-loader` set `workerParallelJobs: 2`. - - -# Content Security Policies - -Webpack is capable of adding `nonce` to all scripts that it loads. To activate the feature set a `__webpack_nonce__` variable needs to be included in your entry script. A unique hash based nonce should be generated and provided for each unique page view this is why `__webpack_nonce__` is specified in the entry file and not in the configuration. Please note that `nonce` should always be a base64-encoded string. - - -## Examples - -In the entry file: - -``` js -// ... -__webpack_nonce__ = 'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM='; -// ... -``` - - -## Enabling CSP - -Please note that CSPs are not enabled by default. A corresponding header `Content-Security-Policy` or meta tag `<meta http-equiv="Content-Security-Policy" ...>` needs to be sent with the document to instruct the browser to enable the CSP. Here's an example of what a CSP header including a CDN white-listed URL might look like: - -``` http -Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; -``` - -For more information on CSP and `nonce` attribute, please refer to __Further Reading__ section at the bottom of this page. - - -# Development - Vagrant - -If you have a more advanced project and use [Vagrant](https://www.vagrantup.com/) to run your development environment in a Virtual Machine, you'll often want to also run webpack in the VM. - -## Configuring the Project - -To start, make sure that the `Vagrantfile` has a static IP; - -```ruby -Vagrant.configure("2") do |config| - config.vm.network :private_network, ip: "10.10.10.61" -end -``` - -Next, install webpack and webpack-dev-server in your project; - -```bash -npm install --save-dev webpack webpack-dev-server -``` - -Make sure to have a `webpack.config.js` file. If you haven't already, use this as a minimal example to get started: - -```js -module.exports = { - context: __dirname, - entry: './app.js' -}; -``` - -And create a `index.html` file. The script tag should point to your bundle. If `output.filename` is not specified in the config, this will be `bundle.js`. - -```html -<!doctype html> -<html> - <head> - <script src="/bundle.js" charset="utf-8"></script> - </head> - <body> - <h2>Heey!</h2> - </body> -</html> -``` - -Note that you also need to create an `app.js` file. - -## Running the Server - -Now, let's run the server: - -```bash -webpack-dev-server --host 0.0.0.0 --public 10.10.10.61:8080 --watch-poll -``` - -By default the server will only be accessible from localhost. We'll be accessing it from our host PC, so we need to change `--host` to allow this. - -webpack-dev-server will include a script in your bundle that connects to a WebSocket to reload when a change in any of your files occurs. -The `--public` flag makes sure the script knows where to look for the WebSocket. The server will use port `8080` by default, so we should also specify that here. - -`--watch-poll` makes sure that webpack can detect changes in your files. By default webpack listens to events triggered by the filesystem, but VirtualBox has many problems with this. - -The server should be accessible on `http://10.10.10.61:8080` now. If you make a change in `app.js`, it should live reload. - -## Advanced Usage with nginx - -To mimic a more production-like environment, it is also possible to proxy the webpack-dev-server with nginx. - -In your nginx config file, add the following: - -```nginx -server { - location / { - proxy_pass http://127.0.0.1:8080; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - error_page 502 @start-webpack-dev-server; - } - - location @start-webpack-dev-server { - default_type text/plain; - return 502 "Please start the webpack-dev-server first."; - } -} -``` - -The `proxy_set_header` lines are important, because they allow the WebSockets to work correctly. - -The command to start webpack-dev-server can then be changed to this: - -```bash -webpack-dev-server --public 10.10.10.61 --watch-poll -``` - -This makes the server only accessible on `127.0.0.1`, which is fine, because nginx takes care of making it available on your host PC. - -## Conclusion - -We made the Vagrant box accessible from a static IP, and then made webpack-dev-server publicly accessible so it is reachable from a browser. We then tackled a common problem that VirtualBox doesn't send out filesystem events, causing the server to not reload on file changes. - - -# Dependency Management - -> es6 modules - -> commonjs - -> amd - - -## require with expression - -A context is created if your request contains expressions, so the __exact__ module is not known on compile time. - -Example: - -```javascript -require('./template/' + name + '.ejs'); -``` - -webpack parses the `require()` call and extracts some information: - -```code -Directory: ./template -Regular expression: /^.*\.ejs$/ -``` - -__context module__ - -A context module is generated. It contains references to __all modules in that directory__ that can be required with a request matching the regular expression. The context module contains a map which translates requests to module ids. - -Example: - -```json -{ - "./table.ejs": 42, - "./table-row.ejs": 43, - "./directory/folder.ejs": 44 -} -``` - -The context module also contains some runtime logic to access the map. - -This means dynamic requires are supported but will cause all possible modules to be included in the bundle. - - -## `require.context` - -You can create your own context with the `require.context()` function. - -It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched -too, and a regular expression to match files against. - -webpack parses for `require.context()` in the code while building. - -The syntax is as follows: - -```javascript -require.context(directory, useSubdirectories = false, regExp = /^\.\//); -``` - -Examples: - -```javascript -require.context('./test', false, /\.test\.js$/); -// a context with files from the test directory that can be required with a request endings with `.test.js`. -``` - -```javascript -require.context('../', true, /\.stories\.js$/); -// a context with all files in the parent folder and descending folders ending with `.stories.js`. -``` - -W> The arguments passed to `require.context` must be literals! - - -### context module API - -A context module exports a (require) function that takes one argument: the request. - -The exported function has 3 properties: `resolve`, `keys`, `id`. - -- `resolve` is a function and returns the module id of the parsed request. -- `keys` is a function that returns an array of all possible requests that the context module can handle. - -This can be useful if you want to require all files in a directory or matching a pattern, Example: - -```javascript -function importAll (r) { - r.keys().forEach(r); -} - -importAll(require.context('../components/', true, /\.js$/)); -``` - -```javascript -var cache = {}; - -function importAll (r) { - r.keys().forEach(key => cache[key] = r(key)); -} - -importAll(require.context('../components/', true, /\.js$/)); -// At build-time cache will be populated with all required modules. -``` - -- `id` is the module id of the context module. This may be useful for `module.hot.accept`. - - -# Public Path - -The `publicPath` configuration option can be quite useful in a variety of scenarios. It allows you to specify the base path for all the assets within your application. - - -## Use Cases - -There are a few use cases in real applications where this feature becomes especially neat. Essentially, every file emitted to your `output.path` directory will be referenced from the `output.publicPath` location. This includes child chunks (created via [code splitting](/guides/code-splitting/)) and any other assets (e.g. images, fonts, etc.) that are a part of your dependency graph. - -### Environment Based - -In development for example, we might have an `assets/` folder that lives on the same level of our index page. This is fine, but what if we wanted to host all these static assets on a CDN in production? - -To approach this problem you can easily use a good old environment variable. Let's say we have a variable `ASSET_PATH`: - -``` js -import webpack from 'webpack'; - -// Try the environment variable, otherwise use root -const ASSET_PATH = process.env.ASSET_PATH || '/'; - -export default { - output: { - publicPath: ASSET_PATH - }, - - plugins: [ - // This makes it possible for us to safely use env vars on our code - new webpack.DefinePlugin({ - 'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH) - }) - ] -}; -``` - -### On The Fly - -Another possible use case is to set the `publicPath` on the fly. webpack exposes a global variable called `__webpack_public_path__` that allows you to do that. So, in your application's entry point, you can simply do this: - -```js -__webpack_public_path__ = process.env.ASSET_PATH; -``` - -That's all you need. Since we're already using the `DefinePlugin` on our -configuration, `process.env.ASSET_PATH` will always be defined so we can safely -do that. - -W> Be aware that if you use ES6 module imports in your entry file the `__webpack_public_path__` assignment will be done after the imports. In such cases, you'll have to move the public path assignment to its own dedicated module and then import it on top of your entry.js: - -```js -// entry.js -import './public-path'; -import './app'; -``` - - -# Integrations - -Let's start by clearing up a common misconception. webpack is a module bundler like [Browserify](http://browserify.org/) or [Brunch](http://brunch.io/). It is _not a task runner_ like [Make](https://www.gnu.org/software/make/), [Grunt](https://gruntjs.com/), or [Gulp](https://gulpjs.com/). Task runners handle automation of common development tasks such as linting, building, or testing your project. Compared to bundlers, task runners have a higher level focus. You can still benefit from their higher level tooling while leaving the problem of bundling to webpack. - -Bundlers help you get your JavaScript and stylesheets ready for deployment, transforming them into a format that's suitable for the browser. For example, JavaScript can be [minified](/plugins/terser-webpack-plugin) or [split into chunks](/guides/code-splitting) and [lazy-loaded](/guides/lazy-loading) to improve performance. Bundling is one of the most important challenges in web development, and solving it well can remove a lot of pain from the process. - -The good news is that, while there is some overlap, task runners and bundlers can play well together if approached in the right way. This guide provides a high-level overview of how webpack can be integrated into some of the more popular task runners. - - -## NPM Scripts - -Often webpack users use npm [`scripts`](https://docs.npmjs.com/misc/scripts) as their task runner. This is a good starting point. Cross-platform support can become a problem, but there are several workarounds for that. Many, if not most users, get by with simple npm `scripts` and various levels of webpack configuration and tooling. - -So while webpack's core focus is bundling, there are a variety of extensions that can enable you to use it for jobs typical of a task runner. Integrating a separate tool adds complexity, so be sure to weigh the pros and cons before going forward. - - -## Grunt - -For those using Grunt, we recommend the [`grunt-webpack`](https://www.npmjs.com/package/grunt-webpack) package. With `grunt-webpack` you can run webpack or [webpack-dev-server](https://github.com/webpack/webpack-dev-server) as a task, get access to stats within [template tags](https://gruntjs.com/api/grunt.template), split development and production configurations and more. Start by installing `grunt-webpack` as well as `webpack` itself if you haven't already: - -``` bash -npm install --save-dev grunt-webpack webpack -``` - -Then register a configuration and load the task: - -__Gruntfile.js__ - -``` js -const webpackConfig = require('./webpack.config.js'); - -module.exports = function(grunt) { - grunt.initConfig({ - webpack: { - options: { - stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development' - }, - prod: webpackConfig, - dev: Object.assign({ watch: true }, webpackConfig) - } - }); - - grunt.loadNpmTasks('grunt-webpack'); -}; -``` - -For more information, please visit the [repository](https://github.com/webpack-contrib/grunt-webpack). - - -## Gulp - -Gulp is also a fairly straightforward integration with the help of the [`webpack-stream`](https://github.com/shama/webpack-stream) package (a.k.a. `gulp-webpack`). In this case, it is unnecessary to install `webpack` separately as it is a direct dependency of `webpack-stream`: - -``` bash -npm install --save-dev webpack-stream -``` - -Just `require('webpack-stream')` instead of `webpack` and optionally pass it an configuration: - -__gulpfile.js__ - -``` js -var gulp = require('gulp'); -var webpack = require('webpack-stream'); -gulp.task('default', function() { - return gulp.src('src/entry.js') - .pipe(webpack({ - // Any configuration options... - })) - .pipe(gulp.dest('dist/')); -}); -``` - -For more information, please visit the [repository](https://github.com/shama/webpack-stream). - - -## Mocha - -The [`mocha-webpack`](https://github.com/zinserjan/mocha-webpack) utility can be used for a clean integration with Mocha. The repository offers more details on the pros and cons but essentially `mocha-webpack` is a simple wrapper that provides almost the same CLI as Mocha itself and provides various webpack functionality like an improved watch mode and improved path resolution. Here is a small example of how you would install it and use it to run a test suite (found within `./test`): - -``` bash -npm install --save-dev webpack mocha mocha-webpack -mocha-webpack 'test/**/*.js' -``` - -For more information, please visit the [repository](https://github.com/zinserjan/mocha-webpack). - - -## Karma - -The [`karma-webpack`](https://github.com/webpack-contrib/karma-webpack) package allows you to use webpack to pre-process files in [Karma](http://karma-runner.github.io/1.0/index.html). It also makes use of [`webpack-dev-middleware`](https://github.com/webpack/webpack-dev-middleware) and allows passing configurations for both. A simple example may look something like this: - -``` bash -npm install --save-dev webpack karma karma-webpack -``` - -__karma.conf.js__ - -``` js -module.exports = function(config) { - config.set({ - files: [ - { pattern: 'test/*_test.js', watched: false }, - { pattern: 'test/**/*_test.js', watched: false } - ], - preprocessors: { - 'test/*_test.js': [ 'webpack' ], - 'test/**/*_test.js': [ 'webpack' ] - }, - webpack: { - // Any custom webpack configuration... - }, - webpackMiddleware: { - // Any custom webpack-dev-middleware configuration... - } - }); -}; -``` - -For more information, please visit the [repository](https://github.com/webpack-contrib/karma-webpack). diff --git a/src/content/loaders/_loaders_all.md b/src/content/loaders/_loaders_all.md deleted file mode 100644 index a16e6814c65b..000000000000 --- a/src/content/loaders/_loaders_all.md +++ /dev/null @@ -1,75 +0,0 @@ - - -# Loaders - -webpack enables use of [loaders](/concepts/loaders) to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js. - -Loaders are activated by using `loadername!` prefixes in `require()` statements, or are automatically applied via regex from your webpack configuration – see [configuration](/concepts/loaders#configuration). - - -## Files - -- [`raw-loader`](/loaders/raw-loader) Loads raw content of a file (utf-8) -- [`val-loader`](/loaders/val-loader) Executes code as module and consider exports as JS code -- [`url-loader`](/loaders/url-loader) Works like the file loader, but can return a [data URL](https://tools.ietf.org/html/rfc2397) if the file is smaller than a limit -- [`file-loader`](/loaders/file-loader) Emits the file into the output folder and returns the (relative) URL -- [`ref-loader`](https://www.npmjs.com/package/ref-loader) Create dependencies between any files manually - - -## JSON - -- [`json-loader`](/loaders/json-loader) Loads a [JSON](http://json.org/) file (included by default) -- [`json5-loader`](/loaders/json5-loader) Loads and transpiles a [JSON 5](https://json5.org/) file -- [`cson-loader`](https://github.com/awnist/cson-loader) Loads and transpiles a [CSON](https://github.com/bevry/cson#what-is-cson) file - - -## Transpiling - -- [`script-loader`](/loaders/script-loader) Executes a JavaScript file once in global context (like in script tag), requires are not parsed -- [`babel-loader`](/loaders/babel-loader) Loads ES2015+ code and transpiles to ES5 using [Babel](https://babeljs.io/) -- [`buble-loader`](https://github.com/sairion/buble-loader) Loads ES2015+ code and transpiles to ES5 using [Bublé](https://buble.surge.sh/guide/) -- [`traceur-loader`](https://github.com/jupl/traceur-loader) Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler#readme) -- [`ts-loader`](https://github.com/TypeStrong/ts-loader) or [`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader) Loads [TypeScript](https://www.typescriptlang.org/) 2.0+ like JavaScript -- [`coffee-loader`](/loaders/coffee-loader) Loads [CoffeeScript](http://coffeescript.org/) like JavaScript -- [`fengari-loader`](https://github.com/fengari-lua/fengari-loader/) Loads Lua code using [fengari](https://fengari.io/) - - -## Templating - -- [`html-loader`](/loaders/html-loader) Exports HTML as string, require references to static resources -- [`pug-loader`](https://github.com/pugjs/pug-loader) Loads Pug and Jade templates and returns a function -- [`markdown-loader`](https://github.com/peerigon/markdown-loader) Compiles Markdown to HTML -- [`react-markdown-loader`](https://github.com/javiercf/react-markdown-loader) Compiles Markdown to a React Component using the markdown-parse parser -- [`posthtml-loader`](https://github.com/posthtml/posthtml-loader) Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) -- [`handlebars-loader`](https://github.com/pcardune/handlebars-loader) Compiles Handlebars to HTML -- [`markup-inline-loader`](https://github.com/asnowwolf/markup-inline-loader) Inline SVG/MathML files to HTML. It’s useful when applying icon font or applying CSS animation to SVG. -- [`twig-loader`](https://github.com/zimmo-be/twig-loader) Compiles Twig templates and returns a function - -## Styling - -- [`style-loader`](/loaders/style-loader) Add exports of a module as style to DOM -- [`css-loader`](/loaders/css-loader) Loads CSS file with resolved imports and returns CSS code -- [`less-loader`](/loaders/less-loader) Loads and compiles a LESS file -- [`sass-loader`](/loaders/sass-loader) Loads and compiles a SASS/SCSS file -- [`postcss-loader`](/loaders/postcss-loader) Loads and transforms a CSS/SSS file using [PostCSS](http://postcss.org) -- [`stylus-loader`](https://github.com/shama/stylus-loader) Loads and compiles a Stylus file - - -## Linting && Testing - -- [`mocha-loader`](/loaders/mocha-loader) Tests with [mocha](https://mochajs.org/) (Browser/NodeJS) -- [`eslint-loader`](https://github.com/webpack-contrib/eslint-loader) PreLoader for linting code using [ESLint](https://eslint.org/) -- [`jshint-loader`](/loaders/jshint-loader) PreLoader for linting code using [JSHint](http://jshint.com/about/) -- [`jscs-loader`](https://github.com/unindented/jscs-loader) PreLoader for code style checking using [JSCS](http://jscs.info/) -- [`coverjs-loader`](/loaders/coverjs-loader) PreLoader to determine the testing coverage using [CoverJS](https://github.com/arian/CoverJS) - - -## Frameworks - -- [`vue-loader`](https://github.com/vuejs/vue-loader) Loads and compiles [Vue Components](https://vuejs.org/v2/guide/components.html) -- [`polymer-loader`](https://github.com/webpack-contrib/polymer-webpack-loader) Process HTML & CSS with preprocessor of choice and `require()` Web Components like first-class modules -- [`angular2-template-loader`](https://github.com/TheLarkInn/angular2-template-loader) Loads and compiles [Angular](https://angular.io/) Components - - - -For more third-party loaders, see the list from [awesome-webpack](https://github.com/webpack-contrib/awesome-webpack#loaders). diff --git a/src/content/migrate/_migrate_all.md b/src/content/migrate/_migrate_all.md deleted file mode 100644 index c0c02cb9ff2b..000000000000 --- a/src/content/migrate/_migrate_all.md +++ /dev/null @@ -1,786 +0,0 @@ - - -# Migrate - -This section contains information about migrating from older versions of webpack to newer ones. - -# To v4 from v3 - -This guide only shows major changes that affect end users. For more details please see [the changelog](https://github.com/webpack/webpack/releases). - - -## Node.js v4 - -If you are still using Node.js v4 or lower, you need to upgrade your Node.js installation to Node.js v6 or higher. - - -## CLI - -The CLI has moved to a separate package: webpack-cli. You need to install it before using webpack, see [basic setup](/guides/getting-started/#basic-setup). - - -## Update plugins - -Many 3rd-party plugins need to be upgraded to their latest version to be compatible. - - -## mode - -Add the new [`mode`](/concepts/mode/) option to your config. Set it to production or development in your configuration depending on config type. - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - mode: 'production', -} -``` - -Alternatively you can pass it via CLI: `--mode production`/`--mode development` - -## Deprecated/Removed plugins - -These plugins can be removed from configuration as they are default in production mode: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NoEmitOnErrorsPlugin(), -- new ModuleConcatenationPlugin(), -- new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }) -- new UglifyJsPlugin() - ], -} -``` - -These plugins are default in development mode - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NamedModulesPlugin() - ], -} -``` - -These plugins were deprecated and are now removed: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NoErrorsPlugin(), -- new NewWatchingPlugin() - ], -} -``` - - -## CommonsChunkPlugin - -The `CommonsChunkPlugin` was removed. Instead the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) options can be used. - -See documentation of the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) for more details. The default configuration may already suit your needs. - -T> When generating the HTML from the stats you can use `optimization.splitChunks.chunks: "all"` which is the optimal configuration in most cases. - -## import() and CommonJS - -When using `import()` to load non-ESM the result has changed in webpack 4. Now you need to access the `default` property to get the value of `module.exports`. - -__non-esm.js__ - -``` javascript -module.exports = { - sayHello: () => { - console.log('hello world'); - } -}; -``` - -__example.js__ - -``` javascript -function sayHello() { - import('./non-esm.js').then(module => { - module.default.sayHello(); - }); -} -``` - -## json and loaders - -When using a custom loader to transform `.json` files you now need to change the module `type`: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - rules: [ - { - test: /config\.json$/, - loader: 'special-loader', -+ type: 'javascript/auto', - options: {...} - } - ] -}; -``` - -When still using the `json-loader`, it can be removed: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - rules: [ - { -- test: /\.json$/, -- loader: 'json-loader' - } - ] -}; -``` - -## module.loaders - -`module.loaders` were deprecated since webpack 2 and are now removed in favor of [`module.rules`](/configuration/module/#rule). - - -# To v2 or v3 from v1 - -The following sections describe the major changes from webpack 1 to 2. - -T> Note that there were far fewer changes between 2 and 3, so that migration shouldn't be too bad. If you are running into issues, please see [the changelog](https://github.com/webpack/webpack/releases) for details. - - -## `resolve.root`, `resolve.fallback`, `resolve.modulesDirectories` - -These options were replaced by a single option `resolve.modules`. See [resolving](/configuration/resolve) for more usage. - -``` diff - resolve: { -- root: path.join(__dirname, "src") -+ modules: [ -+ path.join(__dirname, "src"), -+ "node_modules" -+ ] - } -``` - - -## `resolve.extensions` - -This option no longer requires passing an empty string. This behavior was moved to `resolve.enforceExtension`. See [resolving](/configuration/resolve) for more usage. - - -## `resolve.*` - -Several APIs were changed here. Not listed in detail as it's not commonly used. See [resolving](/configuration/resolve) for details. - - -## `module.loaders` is now `module.rules` - -The old loader configuration was superseded by a more powerful rules system, which allows configuration of loaders and more. -For compatibility reasons, the old `module.loaders` syntax is still valid and the old names are parsed. -The new naming conventions are easier to understand and are a good reason to upgrade the configuration to using `module.rules`. - -``` diff - module: { -- loaders: [ -+ rules: [ - { - test: /\.css$/, -- loaders: [ -- "style-loader", -- "css-loader?modules=true" -+ use: [ -+ { -+ loader: "style-loader" -+ }, -+ { -+ loader: "css-loader", -+ options: { -+ modules: true -+ } -+ } - ] - }, - { - test: /\.jsx$/, - loader: "babel-loader", // Do not use "use" here - options: { - // ... - } - } - ] - } -``` - - -## Chaining loaders - -Like in webpack 1, loaders can be chained to pass results from loader to loader. Using the [rule.use](/configuration/module#rule-use) - configuration option, `use` can be set to an array of loaders. -In webpack 1, loaders were commonly chained with `!`. This style is only supported using the legacy option `module.loaders`. - -``` diff - module: { -- loaders: [{ -+ rules: [{ - test: /\.less$/, -- loader: "style-loader!css-loader!less-loader" -+ use: [ -+ "style-loader", -+ "css-loader", -+ "less-loader" -+ ] - }] - } -``` - - -## Automatic `-loader` module name extension removed - -It is not possible anymore to omit the `-loader` extension when referencing loaders: - -``` diff - module: { - rules: [ - { - use: [ -- "style", -+ "style-loader", -- "css", -+ "css-loader", -- "less", -+ "less-loader", - ] - } - ] - } -``` - -You can still opt-in to the old behavior with the `resolveLoader.moduleExtensions` configuration option, but this is not recommended. - -``` diff -+ resolveLoader: { -+ moduleExtensions: ["-loader"] -+ } -``` - -See [#2986](https://github.com/webpack/webpack/issues/2986) for the reason behind this change. - - -## `json-loader` is not required anymore - -When no loader has been configured for a JSON file, webpack will automatically try to load the JSON -file with the [`json-loader`](https://github.com/webpack-contrib/json-loader). - -``` diff - module: { - rules: [ -- { -- test: /\.json/, -- loader: "json-loader" -- } - ] - } -``` - -[We decided to do this](https://github.com/webpack/webpack/issues/3363) in order to iron out environment differences - between webpack, node.js and browserify. - - -## Loaders in configuration resolve relative to context - -In __webpack 1__, configured loaders resolve relative to the matched file. However, in __webpack 2__, configured loaders resolve relative to the `context` option. - -This solves some problems with duplicate modules caused by loaders when using `npm link` or referencing modules outside of the `context`. - -You may remove some hacks to work around this: - -``` diff - module: { - rules: [ - { - // ... -- loader: require.resolve("my-loader") -+ loader: "my-loader" - } - ] - }, - resolveLoader: { -- root: path.resolve(__dirname, "node_modules") - } -``` - - -## `module.preLoaders` and `module.postLoaders` were removed: - -``` diff - module: { -- preLoaders: [ -+ rules: [ - { - test: /\.js$/, -+ enforce: "pre", - loader: "eslint-loader" - } - ] - } -``` - - -## `UglifyJsPlugin` sourceMap - -The `sourceMap` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. This means that if you are using source maps for minimized code or want correct line numbers for uglifyjs warnings, you need to set `sourceMap: true` for `UglifyJsPlugin`. - -``` diff - devtool: "source-map", - plugins: [ - new UglifyJsPlugin({ -+ sourceMap: true - }) - ] -``` - - -## `UglifyJsPlugin` warnings - -The `compress.warnings` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. -This means that if you want to see uglifyjs warnings, you need to set `compress.warnings` to `true`. - -``` diff - devtool: "source-map", - plugins: [ - new UglifyJsPlugin({ -+ compress: { -+ warnings: true -+ } - }) - ] -``` - - -## `UglifyJsPlugin` minimize loaders - -`UglifyJsPlugin` no longer switches loaders into minimize mode. The `minimize: true` setting needs to be passed via loader options in the long-term. See loader documentation for relevant options. - -The minimize mode for loaders will be removed in webpack 3 or later. - -To keep compatibility with old loaders, loaders can be switched to minimize mode via plugin: - -``` diff - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ minimize: true -+ }) - ] -``` - - -## `DedupePlugin` has been removed - -`webpack.optimize.DedupePlugin` isn't needed anymore. Remove it from your configuration. - - -## `BannerPlugin` - breaking change - -`BannerPlugin` no longer accepts two parameters, but a single options object. - -``` diff - plugins: [ -- new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true}); -+ new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true}); - ] -``` - - -## `OccurrenceOrderPlugin` is now on by default - -The `OccurrenceOrderPlugin` is now enabled by default and has been renamed (`OccurenceOrderPlugin` in webpack 1). -Thus make sure to remove the plugin from your configuration: - -``` diff - plugins: [ - // webpack 1 -- new webpack.optimize.OccurenceOrderPlugin() - // webpack 2 -- new webpack.optimize.OccurrenceOrderPlugin() - ] -``` - - -## `ExtractTextWebpackPlugin` - breaking change - -[ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) requires version 2 to work with webpack 2. - -`npm install --save-dev extract-text-webpack-plugin` - -The configuration changes for this plugin are mainly syntactical. - -### `ExtractTextPlugin.extract` - -```diff -module: { - rules: [ - { - test: /.css$/, -- loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" }) -+ use: ExtractTextPlugin.extract({ -+ fallback: "style-loader", -+ use: "css-loader", -+ publicPath: "/dist" -+ }) - } - ] -} -``` - - -### `new ExtractTextPlugin({options})` - -```diff -plugins: [ -- new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false }) -+ new ExtractTextPlugin({ -+ filename: "bundle.css", -+ disable: false, -+ allChunks: true -+ }) -] -``` - - -## Full dynamic requires now fail by default - -A dependency with only an expression (i. e. `require(expr)`) will now create an empty context instead of the context of the complete directory. - -Code like this should be refactored as it won't work with ES2015 modules. If this is not possible you can use the `ContextReplacementPlugin` to hint the compiler towards the correct resolving. - -?> Link to an article about dynamic dependencies. - -### Using custom arguments in CLI and configuration - -If you abused the CLI to pass custom arguments to the configuration like so: - -`webpack --custom-stuff` - -```js -// webpack.config.js -var customStuff = process.argv.indexOf('--custom-stuff') >= 0; -/* ... */ -module.exports = config; -``` - -You may notice that this is no longer allowed. The CLI is more strict now. - -Instead there is an interface for passing arguments to the configuration. This should be used instead. Future tools may rely on this. - -`webpack --env.customStuff` - -```js -module.exports = function(env) { - var customStuff = env.customStuff; - /* ... */ - return config; -}; -``` - -See [CLI](/api/cli). - - -## `require.ensure` and AMD `require` are asynchronous - -These functions are now always asynchronous instead of calling their callback synchronously if the chunk is already loaded. - -__`require.ensure` now depends upon native `Promise`s. If using `require.ensure` in an environment that lacks them then you will need a polyfill.__ - - -## Loader configuration is through `options` - -You can _no longer_ configure a loader with a custom property in the `webpack.config.js`. It must be done through the `options`. The following configuration with the `ts` property is no longer valid with webpack 2: - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader' - }] - }, - // does not work with webpack 2 - ts: { transpileOnly: false } -}; -``` - - -### What are `options`? - -Good question. Well, strictly speaking it's 2 possible things; both ways to configure a webpack loader. Classically `options` was called `query` and was a string which could be appended to the name of the loader. Much like a query string but actually with [greater powers](https://github.com/webpack/loader-utils#parsequery): - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader?' + JSON.stringify({ transpileOnly: false }) - }] - } -}; -``` - -But it can also be a separately specified object that's supplied alongside a loader: - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader', - options: { transpileOnly: false } - }] - } -}; -``` - - -## `LoaderOptionsPlugin` context - -Some loaders need context information and read them from the configuration. This needs to be passed via loader options in the long-term. See loader documentation for relevant options. - -To keep compatibility with old loaders, this information can be passed via plugin: - -``` diff - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ options: { -+ context: __dirname -+ } -+ }) - ] -``` - - -## `debug` - -The `debug` option switched loaders to debug mode in webpack 1. This needs to be passed via loader options in long-term. See loader documentation for relevant options. - -The debug mode for loaders will be removed in webpack 3 or later. - -To keep compatibility with old loaders, loaders can be switched to debug mode via a plugin: - -``` diff -- debug: true, - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ debug: true -+ }) - ] -``` - - -## Code Splitting with ES2015 - -In webpack 1, you could use [`require.ensure()`](/api/module-methods#require-ensure) as a method to lazily-load chunks for your application: - -```javascript -require.ensure([], function(require) { - var foo = require('./module'); -}); -``` - -The ES2015 Loader spec defines [`import()`](/api/module-methods#import-) as method to load ES2015 Modules dynamically on runtime. webpack treats `import()` as a split-point and puts the requested module in a separate chunk. `import()` takes the module name as argument and returns a Promise. - -```js -function onClick() { - import('./module').then(module => { - return module.default; - }).catch(err => { - console.log('Chunk loading failed'); - }); -} -``` - -Good news: Failure to load a chunk can now be handled because they are `Promise` based. - - -## Dynamic expressions - -It's possible to pass a partial expression to `import()`. This is handled similar to expressions in CommonJS (webpack creates a [context](/plugins/context-replacement-plugin/) with all possible files). - -`import()` creates a separate chunk for each possible module. - -```js -function route(path, query) { - return import(`./routes/${path}/route`) - .then(route => new route.Route(query)); -} -// This creates a separate chunk for each possible route -``` - - -## Mixing ES2015 with AMD and CommonJS - -As for AMD and CommonJS you can freely mix all three module types (even within the same file). webpack behaves similar to babel and node-eps in this case: - -```javascript -// CommonJS consuming ES2015 Module -var book = require('./book'); - -book.currentPage; -book.readPage(); -book.default === 'This is a book'; -``` - -```javascript -// ES2015 Module consuming CommonJS -import fs from 'fs'; // module.exports map to default -import { readFileSync } from 'fs'; // named exports are read from returned object+ - -typeof fs.readFileSync === 'function'; -typeof readFileSync === 'function'; -``` - -It is important to note that you will want to tell Babel to not parse these module symbols so webpack can use them. You can do this by setting the following in your `.babelrc` or `babel-loader` options. - -__.babelrc__ - -```json -{ - "presets": [ - ["es2015", { "modules": false }] - ] -} -``` - - -## Hints - -No need to change something, but opportunities - -### Template strings - -webpack now supports template strings in expressions. This means you can start using them in webpack constructs: - -``` diff -- require("./templates/" + name); -+ require(`./templates/${name}`); -``` - - -### Configuration Promise - -webpack now supports returning a `Promise` from the configuration file. This allows async processing in your configuration file. - -__webpack.config.js__ - -```js -module.exports = function() { - return fetchLangs().then(lang => ({ - entry: '...', - // ... - plugins: [ - new DefinePlugin({ LANGUAGE: lang }) - ] - })); -}; -``` - - -### Advanced loader matching - -webpack now supports more things to match on for loaders. - -```js -module.exports = { - //... - module: { - rules: [ - { - resource: /filename/, // matches "/path/filename.js" - resourceQuery: /^\?querystring$/, // matches "?querystring" - issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js" - } - ] - } -}; -``` - - -### More CLI options - -There are some new CLI options for you to use: - -`--define process.env.NODE_ENV="production"` See [`DefinePlugin`](/plugins/define-plugin/). - -`--display-depth` displays the distance to the entry point for each module. - -`--display-used-exports` display info about which exports are used in a module. - -`--display-max-modules` sets the number for modules displayed in the output (defaults to 15). - -`-p` also defines `process.env.NODE_ENV` to `"production"` now. - - -## Loader changes - -Changes only relevant for loader authors. - - -### Cacheable - -Loaders are now cacheable by default. Loaders must opt-out if they are not cacheable. - -``` diff - // Cacheable loader - module.exports = function(source) { -- this.cacheable(); - return source; - } -``` - -``` diff - // Not cacheable loader - module.exports = function(source) { -+ this.cacheable(false); - return source; - } -``` - - -### Complex options - -__webpack 1__ only supports `JSON.stringify`-able options for loaders. - -__webpack 2__ now supports any JS object as loader options. - -Before webpack [2.2.1](https://github.com/webpack/webpack/releases/tag/v2.2.1) (i.e. from 2.0.0 through 2.2.0), using complex options required using `ident` for the `options` object to allow its reference from other loaders. __This was removed in 2.2.1__ and thus current migrations do not require any use of the `ident` key. - -```diff -{ - test: /\.ext/ - use: { - loader: '...', - options: { -- ident: 'id', - fn: () => require('./foo.js') - } - } -} -``` diff --git a/src/content/plugins/_plugins_all.md b/src/content/plugins/_plugins_all.md deleted file mode 100644 index 65d63475ab80..000000000000 --- a/src/content/plugins/_plugins_all.md +++ /dev/null @@ -1,11 +0,0 @@ - - -# MinChunkSizePlugin - -Keep chunk size above the specified limit by merging chunks that are smaller than the `minChunkSize`. - -``` js -new webpack.optimize.MinChunkSizePlugin({ - minChunkSize: 10000 // Minimum number of characters -}); -``` From df10358b254376dd6abe9d0bd4c8b3bf3cc72a65 Mon Sep 17 00:00:00 2001 From: Eugene Hlushko <jhlushko@gmail.com> Date: Sun, 16 Dec 2018 16:52:10 +0400 Subject: [PATCH 05/13] docs(plugins) IgnorePlugin new syntax and options (#2721) --- src/content/plugins/ignore-plugin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/plugins/ignore-plugin.md b/src/content/plugins/ignore-plugin.md index b7e4ca280b26..f9c3295583d9 100644 --- a/src/content/plugins/ignore-plugin.md +++ b/src/content/plugins/ignore-plugin.md @@ -40,7 +40,7 @@ new webpack.IgnorePlugin({ ## Example of ignoring Moment Locales -As of [moment](https://momentjs.com/) 2.18, all locales are bundled together with the core library (see [this GitHub issue](https://github.com/moment/moment/issues/2373)). +As of [moment](https://momentjs.com/) 2.18, all locales are bundled together with the core library (see [this GitHub issue](https://github.com/moment/moment/issues/2373)). The `resourceRegExp` parameter passed to `IgnorePlugin` is not tested against the resolved file names or absolute module names being imported or required, but rather against the _string_ passed to `require` or `import` _within the source code where the import is taking place_. For example, if you're trying to exclude `node_modules/moment/locale/*.js`, this won't work: From 87933814b37d89720f426360fccf595e0ca8c91e Mon Sep 17 00:00:00 2001 From: sharh <609557623@qq.com> Date: Sun, 16 Dec 2018 21:04:11 +0800 Subject: [PATCH 06/13] docs(plugins): Add title to cacheGroups (#2227) addCache test correctly _describe your changes..._ - [ ] Read and sign the [CLA][1]. PRs that haven't signed it won't be accepted. - [ ] Make sure your PR complies with the [writer's guide][2]. - [ ] Review the diff carefully as sometimes this can reveal issues. - __Remove these instructions from your PR as they are for your eyes only.__ [1]: https://cla.js.foundation/webpack/webpack.js.org [2]: https://webpack.js.org/writers-guide/ --- src/content/plugins/split-chunks-plugin.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/content/plugins/split-chunks-plugin.md b/src/content/plugins/split-chunks-plugin.md index 4c286e910617..a79463c33552 100644 --- a/src/content/plugins/split-chunks-plugin.md +++ b/src/content/plugins/split-chunks-plugin.md @@ -217,6 +217,8 @@ A module can belong to multiple cache groups. The optimization will prefer the c If the current chunk contains modules already split out from the main bundle, it will be reused instead of a new one being generated. This can impact the resulting file name of the chunk. +#### `splitChunks.cacheGroups.cacheGroup.test` + __webpack.config.js__ ```js @@ -255,8 +257,8 @@ module.exports = { } } } - } - } + } + } }; ``` From cf26894cc3b0eadc33ea112567ffb2ffc293a7f8 Mon Sep 17 00:00:00 2001 From: Fernando Montoya <montogeek@gmail.com> Date: Sun, 16 Dec 2018 16:48:42 +0100 Subject: [PATCH 07/13] Update split-chunks-plugin.md --- src/content/plugins/split-chunks-plugin.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/plugins/split-chunks-plugin.md b/src/content/plugins/split-chunks-plugin.md index a79463c33552..3c7c05ac7aff 100644 --- a/src/content/plugins/split-chunks-plugin.md +++ b/src/content/plugins/split-chunks-plugin.md @@ -253,12 +253,12 @@ module.exports = { vendors: { test(module, chunks) { //... - return module.type === 'javascript/auto'; + return module.type === "javascript/auto"; } } } - } - } + } + } }; ``` From 5b45f87a4c031590e89864aa5cdb040aa2938441 Mon Sep 17 00:00:00 2001 From: Fernando Montoya <montogeek@gmail.com> Date: Sun, 16 Dec 2018 17:43:23 +0100 Subject: [PATCH 08/13] Update split-chunks-plugin.md --- src/content/plugins/split-chunks-plugin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/plugins/split-chunks-plugin.md b/src/content/plugins/split-chunks-plugin.md index 3c7c05ac7aff..bbbac6198ce9 100644 --- a/src/content/plugins/split-chunks-plugin.md +++ b/src/content/plugins/split-chunks-plugin.md @@ -253,7 +253,7 @@ module.exports = { vendors: { test(module, chunks) { //... - return module.type === "javascript/auto"; + return module.type === 'javascript/auto'; } } } From d74520b34b7060df89356213ca7a64a4962be2ca Mon Sep 17 00:00:00 2001 From: Eugene Hlushko <jhlushko@gmail.com> Date: Tue, 18 Dec 2018 14:30:57 +0400 Subject: [PATCH 09/13] Revert "cacheGroups" (#2725) * Revert "docs(plugins): Add title to cacheGroups (#2227)" This reverts commit 5b3906e0eb2c196c8d06bf8363b4c84004609e6e. --- src/content/plugins/split-chunks-plugin.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/content/plugins/split-chunks-plugin.md b/src/content/plugins/split-chunks-plugin.md index bbbac6198ce9..4c286e910617 100644 --- a/src/content/plugins/split-chunks-plugin.md +++ b/src/content/plugins/split-chunks-plugin.md @@ -217,8 +217,6 @@ A module can belong to multiple cache groups. The optimization will prefer the c If the current chunk contains modules already split out from the main bundle, it will be reused instead of a new one being generated. This can impact the resulting file name of the chunk. -#### `splitChunks.cacheGroups.cacheGroup.test` - __webpack.config.js__ ```js From 96792a0c4dce99e937c96df9271ef222f95751a0 Mon Sep 17 00:00:00 2001 From: Eugene Hlushko <jhlushko@gmail.com> Date: Thu, 20 Dec 2018 11:36:29 +0400 Subject: [PATCH 10/13] docs(config) document optimization.chunkIds (#2727) * docs(config) document optimization.chunkIds * docs(config) optimization.chunkIds defaults, format strings --- src/content/configuration/optimization.md | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/content/configuration/optimization.md b/src/content/configuration/optimization.md index eddd7ff1419e..cc8bff689feb 100644 --- a/src/content/configuration/optimization.md +++ b/src/content/configuration/optimization.md @@ -250,6 +250,36 @@ module.exports = { }; ``` +## `optimization.chunkIds` + +`bool: false` `string: natural, named, size, total-size` + +Tells webpack which algorithm to use when choosing chunk ids. Setting `optimization.chunkIds` to `false` tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin. There are couple of defaults for `optimization.chunkIds`: + +- if [`optimization.occurrenceOrder`](#optimization-occurrenceorder) is enabled `optimization.chunkIds` is set to `'total-size'` +- Disregarding previous if, if [`optimization.namedChunks`](#optimization-namedchunks) is enabled `optimization.chunkIds` is set to `'named'` +- if none of the above, `optimization.namedChunks` will be defaulted to `'natural'` + +The following string values are supported: + +Option | Description +----------------------- | ----------------------- +`'natural'` | Numeric ids in order of usage. +`'named'` | Readable ids for better debugging. +`'size'` | Numeric ids focused on minimal initial download size. +`'total-size'` | numeric ids focused on minimal total download size. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + chunkIds: 'named' + } +}; +``` + ## `optimization.nodeEnv` `string` `bool: false` From 5c5981d13465f993c772abb19486fe0ab17f216b Mon Sep 17 00:00:00 2001 From: Axel D <SetTrend@users.noreply.github.com> Date: Fri, 14 Dec 2018 16:52:20 +0100 Subject: [PATCH 11/13] CSS rules added for printing, script added to create chapter-wide documentation files from single files. --- src/content/_all.md | 262 + src/content/api/_api_all.md | 3189 ++++++++++ src/content/concepts/_concepts_all.md | 1086 ++++ .../configuration/_configuration_all.md | 5315 +++++++++++++++++ src/content/contribute/_contribute_all.md | 979 +++ src/content/guides/_guides_all.md | 4880 +++++++++++++++ src/content/loaders/_loaders_all.md | 75 + src/content/migrate/_migrate_all.md | 786 +++ src/content/plugins/_plugins_all.md | 11 + 9 files changed, 16583 insertions(+) create mode 100644 src/content/_all.md create mode 100644 src/content/api/_api_all.md create mode 100644 src/content/concepts/_concepts_all.md create mode 100644 src/content/configuration/_configuration_all.md create mode 100644 src/content/contribute/_contribute_all.md create mode 100644 src/content/guides/_guides_all.md create mode 100644 src/content/loaders/_loaders_all.md create mode 100644 src/content/migrate/_migrate_all.md create mode 100644 src/content/plugins/_plugins_all.md diff --git a/src/content/_all.md b/src/content/_all.md new file mode 100644 index 000000000000..fb91d2979380 --- /dev/null +++ b/src/content/_all.md @@ -0,0 +1,262 @@ + + +# Comparison + +webpack is not the only module bundler out there. If you are choosing between using webpack or any of the bundlers below, here is a feature-by-feature comparison on how webpack fares against the current competition. + +| Feature | webpack/webpack | jrburke/requirejs | substack/node-browserify | jspm/jspm-cli | rollup/rollup | brunch/brunch | +|---------|-----------------|-------------------|--------------------------|---------------|---------------|---------------| +| Additional chunks are loaded on demand | __yes__ | __yes__ | no | [System.import](https://github.com/systemjs/systemjs/blob/master/docs/system-api.md#systemimportmodulename--normalizedparentname---promisemodule) | no | no | +| AMD `define` | __yes__ | __yes__ | [deamdify](https://github.com/jaredhanson/deamdify) | yes | [rollup-plugin-amd](https://github.com/piuccio/rollup-plugin-amd) | yes | +| AMD `require` | __yes__ | __yes__ | no | yes | no | yes | +| AMD `require` loads on demand | __yes__ | with manual configuration | no | yes | no | no | +| CommonJS `exports` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | +| CommonJS `require` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | +| CommonJS `require.resolve` | __yes__ | no | no | no | no | | +| Concat in require `require("./fi" + "le")` | __yes__ | no♦ | no | no | no | | +| Debugging support | __SourceUrl, SourceMaps__ | not required | SourceMaps | __SourceUrl, SourceMaps__ | __SourceUrl, SourceMaps__ | SourceMaps | +| Dependencies | 19MB / 127 packages | 11MB / 118 packages | __1.2MB / 1 package__ | 26MB / 131 packages | ?MB / 3 packages | | +| ES2015 `import`/`export` | __yes__ (webpack 2) | no | no | __yes__ | __yes__ | yes, via [es6 module transpiler](https://github.com/gcollazo/es6-module-transpiler-brunch) +| Expressions in require (guided) `require("./templates/" + template)` | __yes (all files matching included)__ | no♦ | no | no | no | no | +| Expressions in require (free) `require(moduleName)` | with manual configuration | no♦ | no | no | no | | +| Generate a single bundle | __yes__ | yes♦ | yes | yes | yes | yes | +| Indirect require `var r = require; r("./file")` | __yes__ | no♦ | no | no | no | | +| Load each file separate | no | yes | no | yes | no | no | +| Mangle path names | __yes__ | no | partial | yes | not required (path names are not included in the bundle) | no | +| Minimizing | terser | uglify, closure compiler | [uglifyify](https://github.com/hughsk/uglifyify) | yes | [uglify-plugin](https://github.com/TrySound/rollup-plugin-uglify) | [UglifyJS-brunch](https://github.com/brunch/uglify-js-brunch) +| Multi pages build with common bundle | with manual configuration | __yes__ | with manual configuration | with bundle arithmetic | no | no| +| Multiple bundles | __yes__ | with manual configuration | with manual configuration | yes | no | yes | +| Node.js built-in libs `require("path")` | __yes__ | no | __yes__ | __yes__ | [node-resolve-plugin](https://github.com/rollup/rollup-plugin-node-resolve) | | +| Other Node.js stuff | process, __dir/filename, global | - | process, __dir/filename, global | process, __dir/filename, global for cjs | global ([commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs)) | | +| Plugins | __yes__ | yes | __yes__ | yes | yes | yes | +| Preprocessing | __loaders, [transforms](https://github.com/webpack-contrib/transform-loader)__ | loaders | transforms | plugin translate | plugin transforms | compilers, optimizers | +| Replacement for browser | `web_modules`, `.web.js`, package.json field, alias config option | alias option | package.json field, alias option | package.json, alias option | no | | +| Requirable files | file system | __web__ | file system | through plugins | file system or through plugins | file system | +| Runtime overhead | __243B + 20B per module + 4B per dependency__ | 14.7kB + 0B per module + (3B + X) per dependency | 415B + 25B per module + (6B + 2X) per dependency | 5.5kB for self-executing bundles, 38kB for full loader and polyfill, 0 plain modules, 293B CJS, 139B ES2015 System.register before gzip | __none for ES2015 modules__ (other formats may have) | | +| Watch mode | yes | not required | [watchify](https://github.com/browserify/watchify) | not needed in dev | [rollup-watch](https://github.com/rollup/rollup-watch) | yes | + +♦ in production mode (opposite in development mode) + +X is the length of the path string + + +## Bundling vs. Loading + +It's important to note some key differences between _loading_ and _bundling_ modules. A tool like [SystemJS](https://github.com/systemjs/systemjs), which can be found under the hood of [JSPM](https://github.com/jspm/jspm-cli), is used to load and transpile modules at runtime in the browser. This differs significantly from webpack, where modules are transpiled (through "loaders") and bundled before hitting the browser. + +Each method has its advantages and disadvantages. Loading and transpiling modules at runtime can add a lot of overhead for larger sites and applications comprised of many modules. For this reason, SystemJS makes more sense for smaller projects where fewer modules are required. However, this may change a bit as [HTTP/2](https://http2.github.io/) will improve the speed at which files can be transferred from server to client. Note that HTTP/2 doesn't change anything about _transpiling_ modules, which will always take longer when done client-side. + + +# Branding Guidelines + +Here you can find __webpack__ project brand guidelines, assets, and license. See our official [media repository](https://github.com/webpack/media) for more information and to find the [license](https://github.com/webpack/media/blob/master/LICENSE) that governs this work. Click any of the images to download them. + + +## The Name + +webpack should __always__ be written in lower-case letters, even at the beginning of a sentence. + + +## Logo + +The webpack logo should be placed on a white background with enough space around it like this: + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-white-bg.png" alt="webpack logo default with proper spacing on light background" /> + +[svg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.jpg) + +Just double the size of the inner dark blue cube to get an idea how much space the logo should have. + +For dark backgrounds, you can use the negative version of the logo: + +<div style="display: block; background: #111;"> + <img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-dark-bg.png" alt="webpack logo default with proper spacing on light background" /> +</div> + +[svg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.jpg) + +T> Please use the __icon + text__ whenever possible. + + +## Icon only + +__The icon is designed to be used in layout-constrained areas. As previously stated, please prefer icon + text.__ + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon.png" width="250" alt="icon example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon.jpg) + +Square-sized icon for bigger areas (like avatars or profile pictures): + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-big.png" width="250" alt="icon square big example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon-square-big.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-big.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-big.jpg) + +Square-sized icon for smaller areas (like favicons): + +<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-small.png" width="50" alt="icon square small example"> + +[svg](https://github.com/webpack/media/blob/master/logo/icon-square-small.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-small.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-small.jpg) + +T> For those of you following our guidelines and have gotten this far, we've made a special smaller size image used especially for custom emoji (like in a slack or gitter channel ;)) + +<img src="/assets/icon-square-small-slack.png" width="50" alt="icon square small example"> + + +## Font + +We use the beautiful [Geomanist Medium](http://atipofoundry.com/fonts/geomanist) font from the extremely talented folks at the [Atipo Foundry](http://atipofoundry.com/) who provide the entire font family at a 'pay what you want' model. + + +## Color Palette + +The following colors are used throughout the site in various combinations and on our fancy clothing line launched with the help of [Open Collective](https://opencollective.com/) and [Threadless](https://medium.com/u/840563ee2a56) over at the [official webpack store](https://webpack.threadless.com/collections/the-final-release-collection/)! + +| Color Name | HEX Code | RGB Code | Sample +|---------------|---------------|-----------------------|------------------------------- +| Malibu: | HEX `#8dd6f9` | `rgb: 141, 214, 249` | <div style="background-color: #8dd6f9;"> </div> +| Denim: | HEX `#1d78c1` | `rgb: 29, 120, 193` | <div style="background-color: #1d78c1;"> </div> +| Fiord: | HEX `#465E69` | `rgb: 70, 94, 105` | <div style="background-color: #465E69;"> </div> +| Outer Space: | HEX `#2B3A42` | `rgb: 43, 58, 66` | <div style="background-color: #2B3A42;"> </div> +| White: | HEX `#ffffff` | `rgb: 255, 255, 255` | <div style="background-color: #ffffff;"> </div> +| Concrete: | HEX `#f2f2f2` | `rgb: 242, 242, 242` | <div style="background-color: #f2f2f2;"> </div> +| Alto: | HEX `#dedede` | `rgb: 222, 222, 222` | <div style="background-color: #dedede;"> </div> +| Dusty Gray: | HEX `#999999` | `rgb: 153, 153, 153` | <div style="background-color: #999999;"> </div> +| Dove Gray: | HEX `#666666` | `rgb: 102, 102, 102` | <div style="background-color: #666666;"> </div> +| Emperor: | HEX `#535353` | `rgb: 83, 83, 83` | <div style="background-color: #535353;"> </div> +| Mine Shaft: | HEX `#333333` | `rgb: 51, 51, 51` | <div style="background-color: #333333;"> </div> + +In addition, you can grab the following file types directly from these links: + +[psd](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.psd) | [png](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.png) + | [ai](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.ai) | [svg](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.svg) + + +## License + +The logo and the brand name are __not MIT licensed__. Please check [our LICENSE](https://github.com/webpack/media/blob/master/LICENSE) for usage guidelines. + + +# Glossary + +This index lists common terms used throughout the webpack ecosystem. + + +## A + +- [__Asset__](/guides/asset-management/): This a general term for the images, fonts, media, and any other kind of files that are typically used in websites and other applications. These typically end up as individual files within the [output](/glossary#o) but can also be inlined via things like the [style-loader](/loaders/style-loader) or [url-loader](/loaders/url-loader). + + +## B + +- [__Bundle__](/guides/getting-started/#creating-a-bundle): Produced from a number of distinct modules, bundles contain the final versions of source files that have already undergone the loading and compilation process. +- [__Bundle Splitting__](/guides/code-splitting): This process offers one way of optimizing a build, allowing webpack to generate multiple bundles for a single application. As a result, each bundle can be isolated from changes effecting others, reducing the amount of code that needs to be republished and therefore re-downloaded by the client and taking advantage of browser caching. + + +## C + +- __Chunk__: This webpack-specific term is used internally to manage the bundling process. Bundles are composed out of chunks, of which there are several types (e.g. entry and child). Typically, _chunks_ directly correspond with the output _bundles_ however, there are some configurations that don't yield a one-to-one relationship. +- [__Code Splitting__](/guides/code-splitting/): Refers to dividing your code into various bundles/chunks which you can then load on demand instead of loading a single bundle containing everything. +- [__Configuration__](/concepts/configuration/): webpack config file is a plain old JavaScript file that exports an object. This object is then processed by webpack based upon its defined properties. + + +## D + +- [__Dependency Graph__](/concepts/dependency-graph): Any time one file depends on another, webpack treats this as a _dependency_. Starting from an entry point(s), webpack recursively builds a dependency graph that includes every module/asset your application needs. + + +## E + +- [__Entry Point__](/concepts/entry-points): The entry point tells webpack where to start and follows the graph of dependencies to know what to bundle. You can think of your application's entry point(s) as the __contextual root(s)__ of what you want bundled. + + +## F + +## G + +## H + +- [__Hot Module Replacement (HMR)__](/concepts/hot-module-replacement): A process that exchanges, adds, or removes `modules` while an application is running without a full page reload. + + +## I + +## J + +## K + +## L + +- [__Loaders__](/concepts/loaders): Transformations that are applied on the source code of a module. They allow you to pre-process files as you `require()` or "load" them. Similar to a 'task-runner'. + + +## M + +- [__Module__](/concepts/modules): Discrete chunks of functionality that provide a smaller surface area than a full program. Well-written modules provide solid abstractions and encapsulation boundaries which make up a coherent design and clear purpose. +- [__Module Resolution__](/concepts/module-resolution/): A module can be required as a dependency from another module and a resolver is a library which helps in locating a module by its absolute path.. Modules are searched for inside all directories specified in `resolve.modules`. + + +## N + +## O + +- [__Output__](/concepts/output): Option(s) specifying where to output the compiled files to disk. + > _Note, that while there can be multiple entry points, only one output configuration is specified._ + + +## P + +- [__Plugin__](/concepts/plugins): A JavaScript object that has an `apply` property. This `apply` property is called by the webpack compiler, giving access to the entire compilation lifecycle. These packages will typically extend compilation functionality in one way or another. + + +## Q + +## R + +- [__Request__](/guides/dependency-management/): Refers to the expression in the require/import statement, e.g. _require("./template/" + name + ".ejs")_, the request is _"./template/" + name + ".ejs"_. + +## S + +## T + +- [__Target__](/configuration/target/): User configured deployment target(s) [listed here](/configuration/target/) to compile for a specific environment like the browser, NodeJS, or Electron. +- [__Tree Shaking__](/guides/tree-shaking/): Unused/Excess code elimination, or more precisely, live code importing. Compilers like webpack will accomplish this by analyzing the various kinds `import` statements and usage of the imported code to determine what parts of dependencies are actually being utilized, dropping parts of the "tree" that are not. + + +## U + +## V + +- [__Vendor Entry Point__](/concepts/entry-points/#separate-app-and-vendor-entries): Create dependency graphs starting at both `app.js` and `vendors.js`. These graphs are completely separate and independent of each other to allow leverage of `CommonsChunkPlugin` and extract any vendor references from your app bundle into your vendor bundle. Helps achieve a common pattern in webpack known as [long-term vendor-caching](/guides/caching/). + + +## W + +- [__webpack__](/): A highly configurable [module](/concepts/modules) bundler for modern JavaScript applications + + +## X + +## Y + +## Z + + +# License + +## webpack + +webpack is [MIT licensed](https://github.com/webpack/webpack/blob/master/LICENSE). + +## webpack logo and icon + +The webpack logo and icon are under a different license which can be +found [here](https://github.com/webpack/media). + +## webpack documentation + +The content on [https://webpack.js.org/](https://webpack.js.org/) is available under [Creative Commons BY 4.0](https://creativecommons.org/licenses/by/4.0/) license meaning attribution is required should you use the content elsewhere. + +## webpack code samples + +The code samples use [CC0 1.0 Universal (CC0 1.0) (Public Domain)](https://creativecommons.org/publicdomain/zero/1.0/) and you are free to use them as you like. diff --git a/src/content/api/_api_all.md b/src/content/api/_api_all.md new file mode 100644 index 000000000000..d54e6da2b86f --- /dev/null +++ b/src/content/api/_api_all.md @@ -0,0 +1,3189 @@ + + +# Compiler Hooks + +The `Compiler` module is the main engine that creates a compilation instance +with all the options passed through the [CLI](/api/cli) or [Node API](/api/node). It extends the +`Tapable` class in order to register and call plugins. Most user facing plugins +are first registered on the `Compiler`. + +T> This module is exposed as `webpack.Compiler` and can be used directly. See +[this example](https://github.com/pksjce/webpack-internal-examples/tree/master/compiler-example) +for more information. + +When developing a plugin for webpack, you might want to know where each hook is called. To learn this, search for `hooks.<hook name>.call` across the webpack source + + +## Watching + +The `Compiler` supports [watching](/api/node/#watching) which monitors the file +system and recompiles as files change. When in watch mode, the compiler will +emit the additional events such as `watchRun`, `watchClose`, and `invalid`. +This is typically used in [development](/guides/development), usually under +the hood of tools like `webpack-dev-server`, so that the developer doesn't +need to re-compile manually every time. Watch mode can also be entered via the +[CLI](/api/cli/#watch-options). + + +## Hooks + +The following lifecycle hooks are exposed by the `compiler` and can be accessed +as such: + +``` js +compiler.hooks.someHook.tap(/* ... */); +``` + +Depending on the hook type, `tapAsync` and `tapPromise` may also be available. + +For the description of hook types, see [the Tapable docs](https://github.com/webpack/tapable#hook-types). + + +### `entryOption` + +`SyncBailHook` + +Executes a plugin after [the `entry` configuration](https://webpack.js.org/configuration/entry-context/#entry) from webpack options has been processed. + + +### `afterPlugins` + +`SyncHook` + +Runs a plugin after setting up initial set of plugins. + +Parameters: `compiler` + + +### `afterResolvers` + +`SyncHook` + +Executes a plugin after resolver setup is complete. + +Parameters: `compiler` + + +### `environment` + +`SyncHook` + +Runs a plugin before the environment is prepared. + + +### `afterEnvironment` + +`SyncHook` + +Executes a plugin a environment setup is complete. + + +### `beforeRun` + +`AsyncSeriesHook` + +Adds a hook right before `compiler.run()` is executed. + +Parameters: `compiler` + + +### `run` + +`AsyncSeriesHook` + +Hook into the compiler before it begins reading records. + +Parameters: `compiler` + + +### `watchRun` + +`AsyncSeriesHook` + +Executes a plugin during watch mode after a new compilation is triggered +but before the compilation is actually started. + +Parameters: `compiler` + + +### `normalModuleFactory` + +`SyncHook` + +Runs a plugin after a `NormalModuleFactory` is created. + +Parameters: `normalModuleFactory` + + +### `contextModuleFactory` + +Runs a plugin after a `ContextModuleFactory` is created. + +Parameters: `contextModuleFactory` + + +### `beforeCompile` + +`AsyncSeriesHook` + +Executes a plugin after compilation parameters are created. + +Parameters: `compilationParams` + + +### `compile` + +`SyncHook` + +Hook into the compiler before a new compilation is created. + +Parameters: `compilationParams` + + +### `thisCompilation` + +`SyncHook` + +Executed before emitting the `compilation` event (see below). + +Parameters: `compilation` + + +### `compilation` + +`SyncHook` + +Runs a plugin after a compilation has been created. + +Parameters: `compilation` + + +### `make` + +`AsyncParallelHook` + +... + +Parameters: `compilation` + + +### `afterCompile` + +`AsyncSeriesHook` + +... + +Parameters: `compilation` + + +### `shouldEmit` + +`SyncBailHook` + +Can return true/false at this point + +Parameters: `compilation` + + +### `emit` + +`AsyncSeriesHook` + +Before emitting assets to output dir + +Parameters: `compilation` + + +### `afterEmit` + +`AsyncSeriesHook` + +After emitting assets to output dir + +Parameters: `compilation` + + +### `done` + +`AsyncSeriesHook` + +Compilation has completed. + +Parameters: `stats` + + +### `failed` + +`SyncHook` + +Compilation has failed. + +Parameters: `error` + + +### `invalid` + +`SyncHook` + +Watch compilation has been invalidated. + +Parameters: `fileName`, `changeTime` + + +### `watchClose` + +`SyncHook` + +Watch mode has stopped. + + +# Introduction + +A variety of interfaces are available to customize the compilation process. +Some features overlap between interfaces, e.g. a configuration option may be +available via a CLI flag, while others exist only through a single interface. +The following high-level information should get you started. + + +## CLI + +The Command Line Interface (CLI) to configure and interact with your build. It +is especially useful in the case of early prototyping and profiling. For the +most part, the CLI is simply used to kick off the process using a configuration +file and a few flags (e.g. `--env`). + +[Learn more about the CLI!](/api/cli) + + +## Module + +When processing modules with webpack, it is important to understand the +different module syntaxes -- specifically the [methods](/api/module-methods) +and [variables](/api/module-variables) -- that are supported. + +[Learn more about modules!](/api/module-methods) + + +## Node + +While most users can get away with just using the CLI along with a +configuration file, more fine-grained control of the compilation can be +achieved via the Node interface. This includes passing multiple configurations, +programmatically running or watching, and collecting stats. + +[Learn more about the Node API!](/api/node) + + +## Loaders + +Loaders are transformations that are applied to the source code of a module. +They are written as functions that accept source code as a parameter and return +a new version of that code with transformations applied. + +[Learn more about loaders!](/api/loaders) + + +## Plugins + +The plugin interface allows users to tap directly into the compilation process. +Plugins can register handlers on lifecycle hooks that run at different points +throughout a compilation. When each hook is executed, the plugin will have full +access to the current state of the compilation. + +[Learn more about plugins!](/api/plugins) + + +# Command Line Interface + +For proper usage and easy distribution of this configuration, webpack can be configured with `webpack.config.js`. Any parameters sent to the CLI will map to a corresponding parameter in the config file. + +Read the [installation guide](/guides/installation) if you don't already have webpack and CLI installed. + + +## Usage with config file + +```sh +webpack [--config webpack.config.js] +``` + +See [configuration](/configuration) for the options in the configuration file. + + +## Usage without config file + +```sh +webpack <entry> [<entry>] -o <output> +``` + +__`<entry>`__ + +A filename or a set of named filenames which act as the entry point to build your project. You can pass multiple entries (every entry is loaded on startup). If you pass a pair in the form `<name>=<request>` you can create an additional entry point. It will be mapped to the configuration option `entry`. + +__`<output>`__ + +A path and filename for the bundled file to be saved in. It will be mapped to the configuration options `output.path` and `output.filename`. + +__Example__ + +If your project structure is as follows - + +```bash +. +├── dist +├── index.html +└── src + ├── index.js + ├── index2.js + └── others.js +``` + +```bash +webpack src/index.js -o dist/bundle.js +``` + +This will bundle your source code with entry as `index.js` and the output bundle file will have a path of `dist` and the filename will be `bundle.js` + +```bash + | Asset | Size | Chunks | Chunk Names | + |-----------|---------|-------------|-------------| + | bundle.js | 1.54 kB | 0 [emitted] | index | + [0] ./src/index.js 51 bytes {0} [built] + [1] ./src/others.js 29 bytes {0} [built] +``` + +```bash +webpack index=./src/index.js entry2=./src/index2.js dist/bundle.js +``` + +This will form the bundle with both the files as separate entry points. + +```bash + | Asset | Size | Chunks | Chunk Names | + |-----------|---------|---------------|---------------| + | bundle.js | 1.55 kB | 0,1 [emitted] | index, entry2 | + [0] ./src/index.js 51 bytes {0} [built] + [0] ./src/index2.js 54 bytes {1} [built] + [1] ./src/others.js 29 bytes {0} {1} [built] +``` + + +### Common Options + +W> Note that Command Line Interface has a higher precedence for the arguments you use it with than your configuration file. For instance, if you pass [`--mode="production"`](/concepts/mode/#usage) to webpack CLI and your configuration file uses `development`, `production` will be used. + +__List all of the options available on the cli__ + +```bash +webpack --help +webpack -h +``` + +__Build source using a config file__ + +Specifies a different [configuration](/configuration) file to pick up. Use this if you want to specify something different than `webpack.config.js`, which is the default. + +```bash +webpack --config example.config.js +``` + +__Print result of webpack as a JSON__ + +```bash +webpack --json +webpack --json > stats.json +``` + +In every other case, webpack prints out a set of stats showing bundle, chunk and timing details. Using this option the output can be a JSON object. This response is accepted by webpack's [analyse tool](https://webpack.github.io/analyse/), or chrisbateman's [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/), or th0r's [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). The analyse tool will take in the JSON and provide all the details of the build in graphical form. + +### Environment Options + +When the webpack configuration [exports a function](/configuration/configuration-types#exporting-a-function), an "environment" may be passed to it. + +```bash +webpack --env.production # sets env.production == true +webpack --env.platform=web # sets env.platform == "web" +``` + +The `--env` argument accepts various syntaxes: + +Invocation | Resulting environment +---------------------------------------- | --------------------------- +`webpack --env prod` | `"prod"` +`webpack --env.prod` | `{ prod: true }` +`webpack --env.prod=1` | `{ prod: 1 }` +`webpack --env.prod=foo` | `{ prod: "foo" }` +`webpack --env.prod --env.min` | `{ prod: true, min: true }` +`webpack --env.prod --env min` | `[{ prod: true }, "min"]` +`webpack --env.prod=foo --env.prod=bar` | `{prod: [ "foo", "bar" ]}` + +T> See the [environment variables](/guides/environment-variables) guide for more information on its usage. + +### Config Options + +Parameter | Explanation | Input type | Default +------------------------- | ------------------------------------------- | ---------- | ------------------ +`--config` | Path to the config file | string | webpack.config.js or webpackfile.js +`--config-register, -r` | Preload one or more modules before loading the webpack configuration | array | +`--config-name` | Name of the config to use | string | +`--env` | Environment passed to the config, when it is a function | | +`--mode` | Mode to use, either "development" or "production" | string | + +### Output Options + +This set of options allows you to manipulate certain [output](/configuration/output) parameters of your build. + +Parameter | Explanation | Input type | Default +------------------------- | ------------------------------------------- | ---------- | ------------------ +`--output-chunk-filename` | The output filename for additional chunks | string | filename with [id] instead of [name] or [id] prefixed +`--output-filename` | The output filename of the bundle | string | [name].js +`--output-jsonp-function` | The name of the JSONP function used for chunk loading | string | webpackJsonp +`--output-library` | Expose the exports of the entry point as library | string | +`--output-library-target` | The type for exposing the exports of the entry point as library | string | var +`--output-path` | The output path for compilation assets | string | Current directory +`--output-pathinfo` | Include a comment with the request for every dependency | boolean | false +`--output-public-path` | The public path for the assets | string | / +`--output-source-map-filename` | The output filename for the SourceMap | string | [name].map or [outputFilename].map +`--build-delimiter` | Display custom text after build output | string | Default string is null. You could provide a string such as `=== Build done ===` + + +#### Example Usage + +```bash +webpack index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' + +| Asset | Size | Chunks | Chunk Names | +|--------------------------------------|---------|-------------|---------------| +| index2740fdca26e9348bedbec.bundle.js | 2.6 kB | 0 [emitted] | index2 | +| index740fdca26e9348bedbec.bundle.js | 2.59 kB | 1 [emitted] | index | + [0] ./src/others.js 29 bytes {0} {1} [built] + [1] ./src/index.js 51 bytes {1} [built] + [2] ./src/index2.js 54 bytes {0} [built] +``` + +```bash +webpack.js index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' --devtool source-map --output-source-map-filename='[name]123.map' + +| Asset | Size | Chunks | Chunk Names | +|--------------------------------------|---------|-------------|---------------| +| index2740fdca26e9348bedbec.bundle.js | 2.76 kB | 0 [emitted] | index2 | +| index740fdca26e9348bedbec.bundle.js | 2.74 kB | 1 [emitted] | index | +| index2123.map | 2.95 kB | 0 [emitted] | index2 | +| index123.map | 2.95 kB | 1 [emitted] | index | + [0] ./src/others.js 29 bytes {0} {1} [built] + [1] ./src/index.js 51 bytes {1} [built] + [2] ./src/index2.js 54 bytes {0} [built] +``` + + +### Debug Options + +This set of options allows you to better debug the application containing assets compiled with webpack + +Parameter | Explanation | Input type | Default value +------------ | ------------------------------------------------ | ---------- | ------------- +`--debug` | Switch loaders to debug mode | boolean | false +`--devtool` | Define [source map type](/configuration/devtool/) for the bundled resources | string | - +`--progress` | Print compilation progress in percentage | boolean | false +`--display-error-details` | Display details about errors | boolean | false + +### Module Options + +These options allow you to bind [modules](/configuration/module/) as allowed by webpack + +Parameter | Explanation | Usage +-------------------- | -------------------------------------- | ---------------- +`--module-bind` | Bind a file extension to a loader | `--module-bind js=babel-loader` +`--module-bind-post` | Bind a file extension to a post loader | +`--module-bind-pre` | Bind a file extension to a pre loader | + + +### Watch Options + +These options makes the build [watch](/configuration/watch/) for changes in files of the dependency graph and perform the build again. + +Parameter | Explanation +------------------------- | ---------------------- +`--watch`, `-w` | Watch the filesystem for changes +`--watch-aggregate-timeout` | Timeout for gathering changes while watching +`--watch-poll` | The polling interval for watching (also enable polling) +`--watch-stdin`, `--stdin` | Exit the process when stdin is closed + + +### Optimize Options + +These options allow you to manipulate optimisations for a production build using webpack + +Parameter | Explanation | Plugin Used +--------------------------- | -------------------------------------------------------|---------------------- +`--optimize-max-chunks` | Try to keep the chunk count below a limit | [LimitChunkCountPlugin](/plugins/limit-chunk-count-plugin) +`--optimize-min-chunk-size` | Try to keep the chunk size above a limit | [MinChunkSizePlugin](/plugins/min-chunk-size-plugin) +`--optimize-minimize` | Minimize javascript and switches loaders to minimizing | [TerserPlugin](/plugins/terser-webpack-plugin/) & [LoaderOptionsPlugin](/plugins/loader-options-plugin/) + + +### Resolve Options + +These allow you to configure the webpack [resolver](/configuration/resolve/) with aliases and extensions. + +Parameter | Explanation | Example +---------------------- | ------------------------------------------------------- | ------------- +`--resolve-alias` | Setup a module alias for resolving | --resolve-alias jquery-plugin=jquery.plugin +`--resolve-extensions` | Setup extensions that should be used to resolve modules | --resolve-extensions .es6 .js .ts +`--resolve-loader-alias` | Minimize javascript and switches loaders to minimizing | + + +### Stats Options + +These options allow webpack to display various [stats](/configuration/stats/) and style them differently in the console output. + +Parameter | Explanation | Type +-------------------------------- | ------------------------------------------------------------------ | ------- +`--color`, `--colors` | Force colors on the console [default: enabled for TTY output only] | boolean +`--no-color`, `--no-colors` | Force no colors on the console | boolean +`--display` | Select [display preset](/configuration/stats) (verbose, detailed, normal, minimal, errors-only, none; since webpack 3.0.0) | string +`--display-cached` | Display also cached modules in the output | boolean +`--display-cached-assets` | Display also cached assets in the output | boolean +`--display-chunks` | Display chunks in the output | boolean +`--display-depth` | Display distance from entry point for each module | boolean +`--display-entrypoints` | Display entry points in the output | boolean +`--display-error-details` | Display details about errors | boolean +`--display-exclude` | Exclude modules in the output | boolean +`--display-max-modules` | Sets the maximum number of visible modules in output | number +`--display-modules` | Display even excluded modules in the output | boolean +`--display-optimization-bailout` | Scope hoisting fallback trigger (since webpack 3.0.0) | boolean +`--display-origins` | Display origins of chunks in the output | boolean +`--display-provided-exports` | Display information about exports provided from modules | boolean +`--display-reasons` | Display reasons about module inclusion in the output | boolean +`--display-used-exports` | Display information about used exports in modules (Tree Shaking) | boolean +`--hide-modules` | Hides info about modules | boolean +`--sort-assets-by` | Sorts the assets list by property in asset | string +`--sort-chunks-by` | Sorts the chunks list by property in chunk | string +`--sort-modules-by` | Sorts the modules list by property in module | string +`--verbose` | Show more details | boolean + + +### Advanced Options + +Parameter | Explanation | Usage +----------------- | ---------------------------------------- | ----- +`--bail` | Abort the compilation on first error | +`--cache` | Enable in memory caching [Enabled by default for watch] | `--cache=false` +`--define` | Define any free variable, see [shimming](/guides/shimming) | `--define process.env.NODE_ENV="'development'"` +`--hot` | Enables [Hot Module Replacement](/concepts/hot-module-replacement) | `--hot=true` +`--labeled-modules` | Enables labeled modules [Uses LabeledModulesPlugin] | +`--plugin` | Load this [plugin](/configuration/plugins/) | +`--prefetch` | Prefetch the particular file | `--prefetch=./files.js` +`--provide` | Provide these modules as globals, see [shimming](/guides/shimming) | `--provide jQuery=jquery` +`--records-input-path` | Path to the records file (reading) | +`--records-output-path` | Path to the records file (writing) | +`--records-path` | Path to the records file | +`--target` | The [targeted](/configuration/target/) execution environment | `--target='node'` + +### Shortcuts + +Shortcut | Replaces +---------|---------------------------- +-d | `--debug --devtool cheap-module-eval-source-map --output-pathinfo` +-p | `--optimize-minimize --define process.env.NODE_ENV="production"`, see [building for production](/guides/production) + +### Profiling + +The `--profile` option captures timing information for each step of the compilation and includes this in the output. + +```bash +webpack --profile + +⋮ +[0] ./src/index.js 90 bytes {0} [built] + factory:22ms building:16ms = 38ms +``` + +For each module, the following details are included in the output as applicable: + +- `factory`: time to collect module metadata (e.g. resolving the filename) +- `building`: time to build the module (e.g. loaders and parsing) +- `dependencies`: time to identify and connect the module’s dependencies + +Paired with `--progress`, `--profile` gives you an in depth idea of which step in the compilation is taking how long. This can help you optimise your build in a more informed manner. + +```bash +webpack --progress --profile + +30ms building modules +1ms sealing +1ms optimizing +0ms basic module optimization +1ms module optimization +1ms advanced module optimization +0ms basic chunk optimization +0ms chunk optimization +1ms advanced chunk optimization +0ms module and chunk tree optimization +1ms module reviving +0ms module order optimization +1ms module id optimization +1ms chunk reviving +0ms chunk order optimization +1ms chunk id optimization +10ms hashing +0ms module assets processing +13ms chunk assets processing +1ms additional chunk assets processing +0ms recording +0ms additional asset processing +26ms chunk asset optimization +1ms asset optimization +6ms emitting +⋮ +``` + + +# Compilation Hooks + +The `Compilation` module is used by the `Compiler` to create new compilations +(or builds). A `compilation` instance has access to all modules and their +dependencies (most of which are circular references). It is the literal +compilation of all the modules in the dependency graph of an application. +During the compilation phase, modules are loaded, sealed, optimized, chunked, +hashed and restored. + +The `Compilation` class also extends `Tapable` and provides the following +lifecycle hooks. They can be tapped the same way as compiler hooks: + +``` js +compilation.hooks.someHook.tap(/* ... */); +``` + +As with the `compiler`, `tapAsync` and `tapPromise` may also be available +depending on the type of hook. + + +### `buildModule` + +`SyncHook` + +Triggered before a module build has started. + +Parameters: `module` + + +### `rebuildModule` + +`SyncHook` + +Fired before rebuilding a module. + +Parameters: `module` + + +### `failedModule` + +`SyncHook` + +Run when a module build has failed. + +Parameters: `module` `error` + + +### `succeedModule` + +`SyncHook` + +Executed when a module has been built successfully. + +Parameters: `module` + + +### `finishModules` + +`SyncHook` + +All modules have been built. + +Parameters: `modules` + + +### `finishRebuildingModule` + +`SyncHook` + +A module has been rebuilt. + +Parameters: `module` + + +### `seal` + +`SyncHook` + +Fired when the compilation stops accepting new modules. + + +### `unseal` + +`SyncHook` + +Fired when a compilation begins accepting new modules. + + +### `optimizeDependenciesBasic` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeDependencies` + +`SyncBailHook` + +Fired at the beginning of dependency optimization. + +Parameters: `modules` + + +### `optimizeDependenciesAdvanced` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `afterOptimizeDependencies` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimize` + +`SyncHook` + +Triggered at the beginning of the optimization phase. + + +### `optimizeModulesBasic` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeModules` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `optimizeModulesAdvanced` + +`SyncBailHook` + +... + +Parameters: `modules` + + +### `afterOptimizeModules` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimizeChunksBasic` + +`SyncBailHook` + +... + +Parameters: `chunks` + + +### `optimizeChunks` + +`SyncBailHook` + +Optimize the chunks. + +Parameters: `chunks` + + +### `optimizeChunksAdvanced` + +`SyncBailHook` + +... + +Parameters: `chunks` + + +### `afterOptimizeChunks` + +`SyncHook` + +Fired after chunk optimization has completed. + +Parameters: `chunks` + + +### `optimizeTree` + +`AsyncSeriesHook` + +Optimize the dependency tree asynchronously. + +Parameters: `chunks` `modules` + + +### `afterOptimizeTree` + +`SyncHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModulesBasic` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModules` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `optimizeChunkModulesAdvanced` + +`SyncBailHook` + +... + +Parameters: `chunks` `modules` + + +### `afterOptimizeChunkModules` + +`SyncHook` + +... + +Parameters: `chunks` `modules` + + +### `shouldRecord` + +`SyncBailHook` + +... + + +### `reviveModules` + +`SyncHook` + +Restore module information from records. + +Parameters: `modules` `records` + + +### `optimizeModuleOrder` + +`SyncHook` + +Sort the modules in from most to least important. + +Parameters: `modules` + + +### `advancedOptimizeModuleOrder` + +`SyncHook` + +... + +Parameters: `modules` + + +### `beforeModuleIds` + +`SyncHook` + +... + +Parameters: `modules` + + +### `moduleIds` + +`SyncHook` + +... + +Parameters: `modules` + + +### `optimizeModuleIds` + +`SyncHook` + +... + +Parameters: `chunks` + + +### `afterOptimizeModuleIds` + +`SyncHook` + +... + +Parameters: `chunks` + + +### `reviveChunks` + +`SyncHook` + +Restore chunk information from records. + +Parameters: `modules` `records` + + +### `optimizeChunkOrder` + +`SyncHook` + +Sort the chunks in from most to least important. + +Parameters: `chunks` + + +### `beforeOptimizeChunkIds` + +`SyncHook` + +Fired before chunk `id` optimization. + +Parameters: `chunks` + + +### `optimizeChunkIds` + +`SyncHook` + +Optimize the `id` of each chunk. + +Parameters: `chunks` + + +### `afterOptimizeChunkIds` + +`SyncHook` + +Triggered after chunk `id` optimization has finished. + +Parameters: `chunks` + + +### `recordModules` + +`SyncHook` + +Store module info to the records. + +Parameters: `modules` `records` + + +### `recordChunks` + +`SyncHook` + +Store chunk info to the records. + +Parameters: `chunks` `records` + + +### `beforeHash` + +`SyncHook` + +Before the compilation is hashed. + + +### `afterHash` + +`SyncHook` + +After the compilation is hashed. + + +### `recordHash` + +`SyncHook` + +... + +Parameters: `records` + + +### `record` + +`SyncHook` + +Store information about the `compilation` to the `records`. + +Parameters: `compilation` `records` + + +### `beforeModuleAssets` + +`SyncHook` + +... + + +### `shouldGenerateChunkAssets` + +`SyncBailHook` + +... + + +### `beforeChunkAssets` + +`SyncHook` + +Before creating the chunk assets. + + +### `additionalChunkAssets` + +`SyncHook` + +Create additional assets for the chunks. + +Parameters: `chunks` + + +### `records` + +`SyncHook` + +... + +Parameters: `compilation` `records` + + +### `additionalAssets` + +`AsyncSeriesHook` + +Create additional assets for the compilation. This hook can be used to download +an image, for example: + +``` js +compilation.hooks.additionalAssets.tapAsync('MyPlugin', callback => { + download('https://img.shields.io/npm/v/webpack.svg', function(resp) { + if(resp.status === 200) { + compilation.assets['webpack-version.svg'] = toAsset(resp); + callback(); + } else { + callback(new Error('[webpack-example-plugin] Unable to download the image')); + } + }); +}); +``` + + +### `optimizeChunkAssets` + +`AsyncSeriesHook` + +Optimize any chunk assets. The assets are stored in `compilation.assets`. A +`Chunk` has a property `files` which points to all files created by a chunk. +Any additional chunk assets are stored in `compilation.additionalChunkAssets`. + +Parameters: `chunks` + +Here's an example that simply adds a banner to each chunk. + +``` js +compilation.hooks + .optimizeChunkAssets + .tapAsync('MyPlugin', (chunks, callback) => { + chunks.forEach(chunk => { + chunk.files.forEach(file => { + compilation.assets[file] = new ConcatSource( + '\/**Sweet Banner**\/', + '\n', + compilation.assets[file] + ); + }); + }); + + callback(); + }); +``` + + +### `afterOptimizeChunkAssets` + +`SyncHook` + +The chunk assets have been optimized. + +Parameters: `chunks` + +Here's an example plugin from [@boopathi](https://github.com/boopathi) that outputs exactly what went into each chunk. + +``` js +compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', chunks => { + chunks.forEach(chunk => { + console.log({ + id: chunk.id, + name: chunk.name, + includes: chunk.modules.map(module => module.request) + }); + }); +}); +``` + + +### `optimizeAssets` + +`AsyncSeriesHook` + +Optimize all assets stored in `compilation.assets`. + +Parameters: `assets` + + +### `afterOptimizeAssets` + +`SyncHook` + +The assets has been optimized. + +Parameters: `assets` + + +### `needAdditionalSeal` + +`SyncBailHook` + +... + + +### `afterSeal` + +`AsyncSeriesHook` + +... + + +### `chunkHash` + +`SyncHook` + +... + +Parameters: `chunk` `chunkHash` + + +### `moduleAsset` + +`SyncHook` + +An asset from a module was added to the compilation. + +Parameters: `module` `filename` + + +### `chunkAsset` + +`SyncHook` + +An asset from a chunk was added to the compilation. + +Parameters: `chunk` `filename` + + +### `assetPath` + +`SyncWaterfallHook` + +... + +Parameters: `filename` `data` + + +### `needAdditionalPass` + +`SyncBailHook` + +... + + +### `childCompiler` + +`SyncHook` + +... + +Parameters: `childCompiler` `compilerName` `compilerIndex` + + +### `normalModuleLoader` + +`SyncHook` + +The normal module loader is the function that actually loads all the modules +in the module graph (one-by-one). + +Parameters: `loaderContext` `module` + +### `dependencyReference` + +`SyncWaterfallHook` + +`Compilation.hooks.dependencyReference(depRef, dependency, module)` allows to change the references reported by dependencies. + +Parameters: `depRef` `dependency` `module` + + +# Module Methods + +This section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including [ES6](https://en.wikipedia.org/wiki/ECMAScript#6th_Edition_-_ECMAScript_2015), [CommonJS](https://en.wikipedia.org/wiki/CommonJS), and [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition). + +W> While webpack supports multiple module syntaxes, we recommend following a single syntax for consistency and to avoid odd behaviors/bugs. Here's [one example](https://github.com/webpack/webpack.js.org/issues/552) of mixing ES6 and CommonJS, however there are surely others. + + +## ES6 (Recommended) + +Version 2 of webpack supports ES6 module syntax natively, meaning you can use `import` and `export` without a tool like babel to handle this for you. Keep in mind that you will still probably need babel for other ES6+ features. The following methods are supported by webpack: + + +### `import` + +Statically `import` the `export`s of another module. + +``` javascript +import MyModule from './my-module.js'; +import { NamedExport } from './other-module.js'; +``` + +W> The keyword here is __statically__. Normal `import` statement cannot be used dynamically within other logic or contain variables. See the [spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) for more information and `import()` below for dynamic usage. + + +### `export` + +Export anything as a `default` or named export. + +``` javascript +// Named exports +export var Count = 5; +export function Multiply(a, b) { + return a * b; +} + +// Default export +export default { + // Some data... +}; +``` + + +### `import()` + +`import('path/to/module') -> Promise` + +Dynamically load modules. Calls to `import()` are treated as split points, meaning the requested module and it's children are split out into a separate chunk. + +T> The [ES2015 Loader spec](https://whatwg.github.io/loader/) defines `import()` as method to load ES2015 modules dynamically on runtime. + +``` javascript +if ( module.hot ) { + import('lodash').then(_ => { + // Do something with lodash (a.k.a '_')... + }); +} +``` + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +The spec for `import` doesn't allow control over the chunk's name or other properties as "chunks" are only a concept within webpack. Luckily webpack allows some special parameters via comments so as to not break the spec: + +``` js +// Single target +import( + /* webpackChunkName: "my-chunk-name" */ + /* webpackMode: "lazy" */ + 'module' +); + +// Multiple possible targets +import( + /* webpackInclude: /\.json$/ */ + /* webpackExclude: /\.noimport\.json$/ */ + /* webpackChunkName: "my-chunk-name" */ + /* webpackMode: "lazy" */ + `./locale/${language}` +); +``` + +```js +import(/* webpackIgnore: true */ 'ignored-module.js'); +``` + +`webpackIgnore`: Disables dynamic import parsing when set to `true`. + +W> Note that setting `webpackIgnore` to `true` opts out of code splitting. + +`webpackChunkName`: A name for the new chunk. Since webpack 2.6.0, the placeholders `[index]` and `[request]` are supported within the given string to an incremented number or the actual resolved filename respectively. + +`webpackMode`: Since webpack 2.6.0, different modes for resolving dynamic imports can be specified. The following options are supported: + +- `"lazy"` (default): Generates a lazy-loadable chunk for each `import()`ed module. +- `"lazy-once"`: Generates a single lazy-loadable chunk that can satisfy all calls to `import()`. The chunk will be fetched on the first call to `import()`, and subsequent calls to `import()` will use the same network response. Note that this only makes sense in the case of a partially dynamic statement, e.g. ``import(`./locales/${language}.json`)``, where there are multiple module paths that could potentially be requested. +- `"eager"`: Generates no extra chunk. All modules are included in the current chunk and no additional network requests are made. A `Promise` is still returned but is already resolved. In contrast to a static import, the module isn't executed until the call to `import()` is made. +- `"weak"`: Tries to load the module if the module function has already been loaded in some other way (i. e. another chunk imported it or a script containing the module was loaded). A `Promise` is still returned but, only successfully resolves if the chunks are already on the client. If the module is not available, the `Promise` is rejected. A network request will never be performed. This is useful for universal rendering when required chunks are always manually served in initial requests (embedded within the page), but not in cases where app navigation will trigger an import not initially served. + +T> Note that all options can be combined like so `/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */`. This is wrapped in a JavaScript object and executed using [node VM](https://nodejs.org/dist/latest-v8.x/docs/api/vm.html). You do not need to add curly brackets. + +`webpackInclude`: A regular expression that will be matched against during import resolution. Only modules that match __will be bundled__. + +`webpackExclude`: A regular expression that will be matched against during import resolution. Any module that matches __will not be bundled__. + +T> Note that `webpackInclude` and `webpackExclude` options do not interfere with the prefix. eg: `./locale`. + +W> Fully dynamic statements, such as `import(foo)`, __will fail__ because webpack requires at least some file location information. This is because `foo` could potentially be any path to any file in your system or project. The `import()` must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files. + +W> Every module that could potentially be requested on an `import()` call is included. For example, ``import(`./locale/${language}.json`)`` will cause every `.json` file in the `./locale` directory to be bundled into the new chunk. At run time, when the variable `language` has been computed, any file like `english.json` or `german.json` will be available for consumption. Using the `webpackInclude` and `webpackExclude` options allows us to add regex patterns that reduce the files that webpack will bundle for this import. + +W> The use of `System.import` in webpack [did not fit the proposed spec](https://github.com/webpack/webpack/issues/2163), so it was deprecated in webpack [2.1.0-beta.28](https://github.com/webpack/webpack/releases/tag/v2.1.0-beta.28) in favor of `import()`. + + +## CommonJS + +The goal of CommonJS is to specify an ecosystem for JavaScript outside the browser. The following CommonJS methods are supported by webpack: + + +### `require` + +``` javascript +require(dependency: String); +``` + +Synchronously retrieve the exports from another module. The compiler will ensure that the dependency is available in the output bundle. + +``` javascript +var $ = require('jquery'); +var myModule = require('my-module'); +``` + +W> Using it asynchronously may not have the expected effect. + + +### `require.resolve` + +``` javascript +require.resolve(dependency: String); +``` + +Synchronously retrieve a module's ID. The compiler will ensure that the dependency is available in the output bundle. See [`module.id`](/api/module-variables#module-id-commonjs-) for more information. + +W> Module ID is a number in webpack (in contrast to NodeJS where it is a string -- the filename). + + +### `require.cache` + +Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. + +W> This is only needed in rare cases for compatibility! + +``` javascript +var d1 = require('dependency'); +require('dependency') === d1; +delete require.cache[require.resolve('dependency')]; +require('dependency') !== d1; +``` + +``` javascript +// in file.js +require.cache[module.id] === module; +require('./file.js') === module.exports; +delete require.cache[module.id]; +require.cache[module.id] === undefined; +require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow +require.cache[module.id] !== module; +``` + + +### `require.ensure` + +W> `require.ensure()` is specific to webpack and superseded by `import()`. + +<!-- eslint-skip --> + +```js +require.ensure( + dependencies: String[], + callback: function(require), + errorCallback: function(error), + chunkName: String +) +``` + +Split out the given `dependencies` to a separate bundle that that will be loaded asynchronously. When using CommonJS module syntax, this is the only way to dynamically load dependencies. Meaning, this code can be run within execution, only loading the `dependencies` if certain conditions are met. + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `require.ensure` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +``` javascript +var a = require('normal-dep'); + +if ( module.hot ) { + require.ensure(['b'], function(require) { + var c = require('c'); + + // Do something special... + }); +} +``` + +The following parameters are supported in the order specified above: + +- `dependencies`: An array of strings declaring all modules required for the code in the `callback` to execute. +- `callback`: A function that webpack will execute once the dependencies are loaded. An implementation of the `require` function is sent as a parameter to this function. The function body can use this to further `require()` modules it needs for execution. +- `errorCallback`: A function that is executed when webpack fails to load the dependencies. +- `chunkName`: A name given to the chunk created by this particular `require.ensure()`. By passing the same `chunkName` to various `require.ensure()` calls, we can combine their code into a single chunk, resulting in only one bundle that the browser must load. + +W> Although the implementation of `require` is passed as an argument to the `callback` function, using an arbitrary name e.g. `require.ensure([], function(request) { request('someModule'); })` isn't handled by webpack's static parser. Use `require` instead, e.g. `require.ensure([], function(require) { require('someModule'); })`. + + + +## AMD + +Asynchronous Module Definition (AMD) is a JavaScript specification that defines an interface for writing and loading modules. The following AMD methods are supported by webpack: + + +### `define` (with factory) + +<!-- eslint-skip --> + +```js +define([name: String], [dependencies: String[]], factoryMethod: function(...)) +``` + +If `dependencies` are provided, `factoryMethod` will be called with the exports of each dependency (in the same order). If `dependencies` are not provided, `factoryMethod` is called with `require`, `exports` and `module` (for compatibility!). If this function returns a value, this value is exported by the module. The compiler ensures that each dependency is available. + +W> Note that webpack ignores the `name` argument. + +``` javascript +define(['jquery', 'my-module'], function($, myModule) { + // Do something with $ and myModule... + + // Export a function + return function doSomething() { + // ... + }; +}); +``` + +W> This CANNOT be used in an asynchronous function. + + +### `define` (with value) + +<!-- eslint-skip --> + +```js +define(value: !Function) +``` + +This will simply export the provided `value`. The `value` here can be anything except a function. + +``` javascript +define({ + answer: 42 +}); +``` + +W> This CANNOT be used in an async function. + + +### `require` (amd-version) + +<!-- eslint-skip --> + +```js +require(dependencies: String[], [callback: function(...)]) +``` + +Similar to `require.ensure`, this will split the given `dependencies` into a separate bundle that will be loaded asynchronously. The `callback` will be called with the exports of each dependency in the `dependencies` array. + +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use AMD with older browsers (e.g. Internet Explorer 11), remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +``` javascript +require(['b'], function(b) { + var c = require('c'); +}); +``` + +W> There is no option to provide a chunk name. + + + +## Labeled Modules + +The internal `LabeledModulesPlugin` enables you to use the following methods for exporting and requiring within your modules: + + +### `export` label + +Export the given `value`. The label can occur before a function declaration or a variable declaration. The function name or variable name is the identifier under which the value is exported. + +<!-- eslint-skip --> + +```js +export: var answer = 42; +export: function method(value) { + // Do something... +}; +``` + +W> Using it in an async function may not have the expected effect. + + +### `require` label + +Make all exports from the dependency available in the current scope. The `require` label can occur before a string. The dependency must export values with the `export` label. CommonJS or AMD modules cannot be consumed. + +__some-dependency.js__ + +<!-- eslint-skip --> + +```js +export: var answer = 42; +export: function method(value) { + // Do something... +}; +``` + +<!-- eslint-skip --> + +```js +require: 'some-dependency'; +console.log(answer); +method(...); +``` + + + +## Webpack + +Aside from the module syntaxes described above, webpack also allows a few custom, webpack-specific methods: + + +### `require.context` + +<!-- eslint-skip --> + +```js +require.context( + directory: String, + includeSubdirs: Boolean /* optional, default true */, + filter: RegExp /* optional, default /^\.\/.*$/, any file */, + mode: String /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */ +) +``` + +Specify a whole group of dependencies using a path to the `directory`, an option to `includeSubdirs`, a `filter` for more fine grained control of the modules included, and a `mode` to define the way how loading will work. Underlying modules can then be easily resolved later on: + +```javascript +var context = require.context('components', true, /\.html$/); +var componentA = context.resolve('componentA'); +``` + +If `mode` is specified as "lazy", the underlying modules will be loaded asynchronously: + +```javascript +var context = require.context('locales', true, /\.json$/, 'lazy'); +context('localeA').then(locale => { + // do something with locale +}); +``` + +The full list of available modes and its behavior is described in [`import()`](#import-) documentation. + +### `require.include` + +<!-- eslint-skip --> + +```js +require.include(dependency: String) +``` + +Include a `dependency` without executing it. This can be used for optimizing the position of a module in the output chunks. + +``` javascript +require.include('a'); +require.ensure(['a', 'b'], function(require) { /* ... */ }); +require.ensure(['a', 'c'], function(require) { /* ... */ }); +``` + +This will result in following output: + +- entry chunk: `file.js` and `a` +- anonymous chunk: `b` +- anonymous chunk: `c` + +Without `require.include('a')` it would be duplicated in both anonymous chunks. + + +### `require.resolveWeak` + +Similar to `require.resolve`, but this won't pull the `module` into the bundle. It's what is considered a "weak" dependency. + +``` javascript +if(__webpack_modules__[require.resolveWeak('module')]) { + // Do something when module is available... +} +if(require.cache[require.resolveWeak('module')]) { + // Do something when module was loaded before... +} + +// You can perform dynamic resolves ("context") +// just as with other require/import methods. +const page = 'Foo'; +__webpack_modules__[require.resolveWeak(`./page/${page}`)]; +``` + +T> `require.resolveWeak` is the foundation of _universal rendering_ (SSR + Code Splitting), as used in packages such as [react-universal-component](https://github.com/faceyspacey/react-universal-component). It allows code to render synchronously on both the server and initial page-loads on the client. It requires that chunks are manually served or somehow available. It's able to require modules without indicating they should be bundled into a chunk. It's used in conjunction with `import()` which takes over when user navigation triggers additional imports. + + +# Node.js API + +webpack provides a Node.js API which can be used directly in Node.js runtime. + +The Node.js API is useful in scenarios in which you need to customize the build or development process since all the reporting and error handling must be done manually and webpack only does the compiling part. For this reason the [`stats`](/configuration/stats) configuration options will not have any effect in the `webpack()` call. + + +## Installation + +To start using webpack Node.js API, first install webpack if you haven’t yet: + +``` bash +npm install --save-dev webpack +``` + +Then require the webpack module in your Node.js script: + +``` js +const webpack = require('webpack'); +``` + +Or if you prefer ES2015: + +``` js +import webpack from 'webpack'; +``` + + +## `webpack()` + +The imported `webpack` function is fed a webpack [Configuration Object](/configuration/) and runs the webpack compiler if a callback function is provided: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, [stats](#stats-object)) => { + if (err || stats.hasErrors()) { + // [Handle errors here](#error-handling) + } + // Done processing +}); +``` + +T> The `err` object __will not__ include compilation errors and those must be handled separately using `stats.hasErrors()` which will be covered in detail in [Error Handling](#error-handling) section of this guide. The `err` object will only contain webpack-related issues, such as misconfiguration, etc. + +T> You can provide the `webpack` function with an array of configurations. See +the [MultiCompiler](#multicompiler) section below for more information. + + +## Compiler Instance + +If you don’t pass the `webpack` runner function a callback, it will return a +webpack `Compiler` instance. This instance can be used to manually trigger the +webpack runner or have it build and watch for changes, much like the +[CLI](/api/cli/). The `Compiler` instance provides the following methods: + +- `.run(callback)` +- `.watch(watchOptions, handler)` + +Typically, only one master `Compiler` instance is created, although child +compilers can be created in order to delegate specific tasks. The `Compiler` is +ultimately just a function which performs bare minimum functionality to keep a +lifecycle running. It delegates all the loading, bundling, and writing work to +registered plugins. + +The `hooks` property on a `Compiler` instance is used to register a plugin to +any hook event in the `Compiler`'s lifecycle. The +[`WebpackOptionsDefaulter`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js) +and [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js) +utilities are used by webpack to configure its `Compiler` instance with all the +built-in plugins. + +The `run` method is then used to kickstart all compilation work. Upon +completion, the given `callback` function is executed. The final logging of +stats and errors should be done in this `callback` function. + +W> The API only supports a single concurrent compilation at a time. When using +`run`, wait for it to finish before calling `run` or `watch` again. When using +`watch`, call `close` and wait for it to finish before calling `run` or `watch` +again. Concurrent compilations will corrupt the output files. + + +## Run + +Calling the `run` method on the `Compiler` instance is much like the quick run +method mentioned above: + +``` js-with-links +const webpack = require("webpack"); + +const compiler = webpack({ + // [Configuration Object](/configuration/) +}); + +compiler.run((err, [stats](#stats-object)) => { + // ... +}); +``` + + +## Watching + +Calling the `watch` method, triggers the webpack runner, but then watches for +changes (much like CLI: `webpack --watch`), as soon as webpack detects a +change, runs again. Returns an instance of `Watching`. + +``` js +watch(watchOptions, callback); +``` + +``` js-with-links +const webpack = require("webpack"); + +const compiler = webpack({ + // [Configuration Object](/configuration/) +}); + +const watching = compiler.watch({ + // Example [watchOptions](/configuration/watch/#watchoptions) + aggregateTimeout: 300, + poll: undefined +}, (err, [stats](#stats-object)) => { + // Print watch/build result here... + console.log(stats); +}); +``` + +`Watching` options are covered in detail +[here](/configuration/watch/#watchoptions). + +W> Filesystem inaccuracies may trigger multiple builds for a single change. So, +in the example above, the `console.log` statement may fire multiple times for a +single modification. Users should expect this behavior and may check +`stats.hash` to see if the file hash has actually changed. + + +### Close `Watching` + +The `watch` method returns a `Watching` instance that exposes +`.close(callback)` method. Calling this method will end watching: + +``` js +watching.close(() => { + console.log('Watching Ended.'); +}); +``` + +W> It’s not allowed to watch or run again before the existing watcher has been +closed or invalidated. + + +### Invalidate `Watching` + +Using `watching.invalidate`, you can manually invalidate the current compiling +round, without stopping the watch process: + +``` js +watching.invalidate(); +``` + + +## Stats Object + +The `stats` object that is passed as a second argument of the +[`webpack()`](#webpack-) callback, is a good source of information about the +code compilation process. It includes: + +- Errors and Warnings (if any) +- Timings +- Module and Chunk information + +The [webpack CLI](/api/cli) uses this information to display nicely formatted +output in your console. + +T> When using the [`MultiCompiler`](/api/plugins/compiler#multicompiler), a +`MultiStats` instance is returned that fulfills the same interface as `stats`, +i.e. the methods described below. + +This `stats` object exposes the following methods: + + +### `stats.hasErrors()` + +Can be used to check if there were errors while compiling. Returns `true` or +`false`. + + +### `stats.hasWarnings()` + +Can be used to check if there were warnings while compiling. Returns `true` or +`false`. + + +### `stats.toJson(options)` + +Returns compilation information as a JSON object. `options` can be either a +string (a preset) or an object for more granular control: + +``` js-with-links +stats.toJson("minimal"); // [more options: "verbose", etc](/configuration/stats). +``` + +``` js +stats.toJson({ + assets: false, + hash: true +}); +``` + +All available options and presets are described in the stats [documentation](/configuration/stats). + +> Here’s an [example] +(https://github.com/webpack/analyse/blob/master/app/pages/upload/example.json) +of this function’s output. + + +### `stats.toString(options)` + +Returns a formatted string of the compilation information (similar to +[CLI](/api/cli) output). + +Options are the same as [`stats.toJson(options)`](/api/node#stats-tojson-options-) with one addition: + +``` js +stats.toString({ + // Add console colors + colors: true +}); +``` + +Here’s an example of `stats.toString()` usage: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, stats) => { + if (err) { + console.error(err); + return; + } + + console.log(stats.toString({ + chunks: false, // Makes the build much quieter + colors: true // Shows colors in the console + })); +}); +``` + + +## MultiCompiler + +The `MultiCompiler` module allows webpack to run multiple configurations in +separate compilers. If the `options` parameter in the webpack's NodeJS api is +an array of options, webpack applies separate compilers and calls the +`callback` method at the end of each compiler execution. + +``` js-with-links +var webpack = require('webpack'); + +webpack([ + { entry: './index1.js', output: { filename: 'bundle1.js' } }, + { entry: './index2.js', output: { filename: 'bundle2.js' } } +], (err, [stats](#stats-object)) => { + process.stdout.write(stats.toString() + "\n"); +}) +``` + +W> Multiple configurations will __not be run in parallel__. Each +configuration is only processed after the previous one has finished +processing. To process them in parallel, you can use a third-party solution +like [parallel-webpack](https://www.npmjs.com/package/parallel-webpack). + + +## Error Handling + +For a good error handling, you need to account for these three types of errors: + +- Fatal webpack errors (wrong configuration, etc) +- Compilation errors (missing modules, syntax errors, etc) +- Compilation warnings + +Here’s an example that does all that: + +``` js-with-links +const webpack = require("webpack"); + +webpack({ + // [Configuration Object](/configuration/) +}, (err, stats) => { + if (err) { + console.error(err.stack || err); + if (err.details) { + console.error(err.details); + } + return; + } + + const info = stats.toJson(); + + if (stats.hasErrors()) { + console.error(info.errors); + } + + if (stats.hasWarnings()) { + console.warn(info.warnings); + } + + // Log result... +}); +``` + + +## Custom File Systems + +By default, webpack reads files and writes files to disk using a normal file +system. However, it is possible to change the input or output behavior using a +different kind of file system (memory, webDAV, etc). To accomplish this, one +can change the `inputFileSystem` or `outputFileSystem`. For example, you can +replace the default `outputFileSystem` with +[`memory-fs`](https://github.com/webpack/memory-fs) to write files to memory +instead of to disk: + +``` js +const MemoryFS = require('memory-fs'); +const webpack = require('webpack'); + +const fs = new MemoryFS(); +const compiler = webpack({ /* options*/ }); + +compiler.outputFileSystem = fs; +compiler.run((err, stats) => { + // Read the output later: + const content = fs.readFileSync('...'); +}); +``` + +Note that this is what +[webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware), +used by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) +and many other packages, uses to mysteriously hide your files but continue +serving them up to the browser! + +T> The output file system you provide needs to be compatible with Node’s own +[`fs`](https://nodejs.org/api/fs.html) interface, which requires the `mkdirp` +and `join` helper methods. + + +# Resolvers + +Resolvers are created using the `enhanced-resolve` package. The `Resolver` +class extends the `tapable` class and uses `tapable` to provide a few hooks. +The `enhanced-resolve` package can be used directly to create new resolvers, +however any [`compiler` instance](/api/node/#compiler-instance) has a few resolver instances that can be +tapped into. + +Before reading on, make sure you at least skim through the +[`enhanced-resolve`](https://github.com/webpack/enhanced-resolve) and [`tapable`](/api/plugins/#tapable) documentation. + + +## Types + +There are three types of built-in resolvers available on the `compiler` class: + +- Normal: Resolves a module via an absolute or relative path. +- Context: Resolves a module within a given context. +- Loader: Resolves a webpack [loader](/loaders). + +Depending on need, any one of these built-in resolver used by the `compiler` +can be customized via plugins as such: + +``` js +compiler.resolverFactory.plugin('resolver [type]', resolver => { + resolver.hooks.resolve.tapAsync('MyPlugin', params => { + // ... + }); +}); +``` + +Where `[type]` is one of the three resolvers mention above, specified as: + +- `normal` +- `context` +- `loader` + + +See the `enhanced-resolve` [documentation](https://github.com/webpack/enhanced-resolve) for a full list of hooks and +descriptions. + + +## Configuration Options + +The resolvers mentioned above can also be customized via a configuration file +with the [`resolve`](/configuration/resolve/) or [`resolveLoader`](/configuration/resolve/#resolveloader) options. These options allow +users to change the resolving behavior through a variety of options including +through resolve `plugins`. + +The resolver plugins, e.g. [`DirectoryNamedPlugin`](https://github.com/shaketbaby/directory-named-webpack-plugin), can be included +directly in `resolve.plugins` rather than using standard plugins. Note that the +`resolve` configuration affects the `normal` and `context` resolvers while +`resolveLoader` is used to modify the `loader` resolver. + + +# Stats Data + +When compiling source code with webpack, users can generate a JSON file containing statistics about modules. These statistics can be used to analyze an application's dependency graph as well as to optimize compilation speed. The file is typically generated with the following CLI command: + +``` bash +webpack --profile --json > compilation-stats.json +``` + +The `--json > compilation-stats.json` flag indicates to webpack that it should emit the `compilation-stats.json` containing the dependency graph and various other build information. Typically, the `--profile` flag is also added so that a `profile` section is added to each [`modules` object](#module-objects) containing module-specific compilation stats. + + +## Structure + +The top-level structure of the output JSON file is fairly straightforward but there are a few nested data structures as well. Each nested structure has a dedicated section below to make this document more consumable. Note that you can click links within the top-level structure below to jump to relevant sections and documentation: + +```js-with-links +{ + "version": "1.4.13", // Version of webpack used for the compilation + "hash": "11593e3b3ac85436984a", // Compilation specific hash + "time": 2469, // Compilation time in milliseconds + "filteredModules": 0, // A count of excluded modules when [`exclude`](/configuration/stats/#stats) is passed to the [`toJson`](/api/node/#stats-tojson-options-) method + "outputPath": "/", // path to webpack output directory + "assetsByChunkName": { + // Chunk name to emitted asset(s) mapping + "main": "web.js?h=11593e3b3ac85436984a", + "named-chunk": "named-chunk.web.js", + "other-chunk": [ + "other-chunk.js", + "other-chunk.css" + ] + }, + "assets": [ + // A list of [asset objects](#asset-objects) + ], + "chunks": [ + // A list of [chunk objects](#chunk-objects) + ], + "modules": [ + // A list of [module objects](#module-objects) + ], + "errors": [ + // A list of [error strings](#errors-and-warnings) + ], + "warnings": [ + // A list of [warning strings](#errors-and-warnings) + ] +} +``` + + +### Asset Objects + +Each `assets` object represents an `output` file emitted from the compilation. They all follow a similar structure: + +<!-- eslint-skip --> + +```js +{ + "chunkNames": [], // The chunks this asset contains + "chunks": [ 10, 6 ], // The chunk IDs this asset contains + "emitted": true, // Indicates whether or not the asset made it to the `output` directory + "name": "10.web.js", // The `output` filename + "size": 1058 // The size of the file in bytes +} +``` + + +### Chunk Objects + +Each `chunks` object represents a group of modules known as a [chunk](/glossary#c). Each object follows the following structure: + +```js-with-links +{ + "entry": true, // Indicates whether or not the chunk contains the webpack runtime + "files": [ + // An array of filename strings that contain this chunk + ], + "filteredModules": 0, // See the description in the [top-level structure](#structure) above + "id": 0, // The ID of this chunk + "initial": true, // Indicates whether this chunk is loaded on initial page load or [on demand](/guides/lazy-loading) + "modules": [ + // A list of [module objects](#module-objects) + "web.js?h=11593e3b3ac85436984a" + ], + "names": [ + // An list of chunk names contained within this chunk + ], + "origins": [ + // See the description below... + ], + "parents": [], // Parent chunk IDs + "rendered": true, // Indicates whether or not the chunk went through Code Generation + "size": 188057 // Chunk size in bytes +} +``` + +The `chunks` object will also contain a list of `origins` describing how the given chunk originated. Each `origins` object follows the following schema: + +```js-with-links +{ + "loc": "", // Lines of code that generated this chunk + "module": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleId": 0, // The ID of the module + "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleName": "./lib/index.web.js", // Relative path to the module + "name": "main", // The name of the chunk + "reasons": [ + // A list of the same `reasons` found in [module objects](#module-objects) + ] +} +``` + + +### Module Objects + +What good would these statistics be without some description of the compiled application's actual modules? Each module in the dependency graph is represented by the following structure: + +```js-with-links +{ + "assets": [ + // A list of [asset objects](#asset-objects) + ], + "built": true, // Indicates that the module went through [Loaders](/concepts/loaders), Parsing, and Code Generation + "cacheable": true, // Whether or not this module is cacheable + "chunks": [ + // IDs of chunks that contain this module + ], + "errors": 0, // Number of errors when resolving or processing the module + "failed": false, // Whether or not compilation failed on this module + "id": 0, // The ID of the module (analagous to [`module.id`](/api/module-variables#module-id-commonjs-)) + "identifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // A unique ID used internally + "name": "./lib/index.web.js", // Path to the actual file + "optional": false, // All requests to this module are with `try... catch` blocks (irrelevant with ESM) + "prefetched": false, // Indicates whether or not the module was [prefetched](/plugins/prefetch-plugin) + "profile": { + // Module specific compilation stats corresponding to the [`--profile` flag](/api/cli#profiling) (in milliseconds) + "building": 73, // Loading and parsing + "dependencies": 242, // Building dependencies + "factory": 11 // Resolving dependencies + }, + "reasons": [ + // See the description below... + ], + "size": 3593, // Estimated size of the module in bytes + "source": "// Should not break it...\r\nif(typeof...", // The stringified raw source + "warnings": 0 // Number of warnings when resolving or processing the module +} +``` + +Every module also contains a list of `reasons` objects describing why that module was included in the dependency graph. Each "reason" is similar to the `origins` seen above in the [chunk objects](#chunk-objects) section: + +```js-with-links +{ + "loc": "33:24-93", // Lines of code that caused the module to be included + "module": "./lib/index.web.js", // Relative path to the module based on [context](/configuration/entry-context/#context) + "moduleId": 0, // The ID of the module + "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module + "moduleName": "./lib/index.web.js", // A more readable name for the module (used for "pretty-printing") + "type": "require.context", // The [type of request](/api/module-methods) used + "userRequest": "../../cases" // Raw string used for the `import` or `require` request +} +``` + + +### Errors and Warnings + +The `errors` and `warnings` properties each contain a list of strings. Each string contains a message and stack trace: + +``` bash +../cases/parsing/browserify/index.js +Critical dependencies: +2:114-121 This seem to be a pre-built javascript file. Even while this is possible, it's not recommended. Try to require to original source to get better results. + @ ../cases/parsing/browserify/index.js 2:114-121 +``` + +W> Note that the stack traces are removed when `errorDetails: false` is passed to the `toJson` method. The `errorDetails` option is set to `true` by default. + + +# Loader API + +A loader is just a JavaScript module that exports a function. The [loader runner](https://github.com/webpack/loader-runner) calls this function and passes the result of the previous loader or the resource file into it. The `this` context of the function is filled-in by webpack and the [loader runner](https://github.com/webpack/loader-runner) with some useful methods that allow the loader (among other things) to change its invocation style to async, or get query parameters. + +The first loader is passed one argument: the content of the resource file. The compiler expects a result from the last loader. The result should be a `String` or a `Buffer` (which is converted to a string), representing the JavaScript source code of the module. An optional SourceMap result (as JSON object) may also be passed. + +A single result can be returned in __sync mode__. For multiple results the `this.callback()` must be called. In __async mode__ `this.async()` must be called to indicate that the [loader runner](https://github.com/webpack/loader-runner) should wait for an asynchronous result. It returns `this.callback()`. Then the loader must return `undefined` and call that callback. + + +## Examples + +The following sections provide some basic examples of the different types of loaders. Note that the `map` and `meta` parameters are optional, see [`this.callback`](/api/loaders#this-callback) below. + +### Synchronous Loaders + +Either `return` or `this.callback` can be used to return the transformed `content` synchronously: + +__sync-loader.js__ + +``` js +module.exports = function(content, map, meta) { + return someSyncOperation(content); +}; +``` + +The `this.callback` method is more flexible as it allows multiple arguments to be passed as opposed to just the `content`. + +__sync-loader-with-multiple-results.js__ + +``` js +module.exports = function(content, map, meta) { + this.callback(null, someSyncOperation(content), map, meta); + return; // always return undefined when calling callback() +}; +``` + +### Asynchronous Loaders + +For asynchronous loaders, [`this.async`](/api/loaders#this-async) is used to retrieve the `callback` function: + +__async-loader.js__ + +``` js +module.exports = function(content, map, meta) { + var callback = this.async(); + someAsyncOperation(content, function(err, result) { + if (err) return callback(err); + callback(null, result, map, meta); + }); +}; +``` + +__async-loader-with-multiple-results.js__ + +``` js +module.exports = function(content, map, meta) { + var callback = this.async(); + someAsyncOperation(content, function(err, result, sourceMaps, meta) { + if (err) return callback(err); + callback(null, result, sourceMaps, meta); + }); +}; +``` + +T> Loaders were originally designed to work in synchronous loader pipelines, like Node.js (using [enhanced-require](https://github.com/webpack/enhanced-require)), _and_ asynchronous pipelines, like in webpack. However, since expensive synchronous computations are a bad idea in a single-threaded environment like Node.js, we advise to make your loader asynchronously if possible. Synchronous loaders are ok if the amount of computation is trivial. + + +### "Raw" Loader + +By default, the resource file is converted to a UTF-8 string and passed to the loader. By setting the `raw` flag, the loader will receive the raw `Buffer`. Every loader is allowed to deliver its result as `String` or as `Buffer`. The compiler converts them between loaders. + +__raw-loader.js__ + +``` js +module.exports = function(content) { + assert(content instanceof Buffer); + return someSyncOperation(content); + // return value can be a `Buffer` too + // This is also allowed if loader is not "raw" +}; +module.exports.raw = true; +``` + + +### Pitching Loader + +Loaders are __always__ called from right to left. There are some instances where the loader only cares about the __metadata__ behind a request and can ignore the results of the previous loader. The `pitch` method on loaders is called from __left to right__ before the loaders are actually executed (from right to left). For the following [`use`](/configuration/module#rule-use) configuration: + +``` js +module.exports = { + //... + module: { + rules: [ + { + //... + use: [ + 'a-loader', + 'b-loader', + 'c-loader' + ] + } + ] + } +}; +``` + +These steps would occur: + +``` diff +|- a-loader `pitch` + |- b-loader `pitch` + |- c-loader `pitch` + |- requested module is picked up as a dependency + |- c-loader normal execution + |- b-loader normal execution +|- a-loader normal execution +``` + +So why might a loader take advantage of the "pitching" phase? + +First, the `data` passed to the `pitch` method is exposed in the execution phase as well under `this.data` and could be useful for capturing and sharing information from earlier in the cycle. + +``` js +module.exports = function(content) { + return someSyncOperation(content, this.data.value); +}; + +module.exports.pitch = function(remainingRequest, precedingRequest, data) { + data.value = 42; +}; +``` + +Second, if a loader delivers a result in the `pitch` method the process turns around and skips the remaining loaders. In our example above, if the `b-loader`s `pitch` method returned something: + +``` js +module.exports = function(content) { + return someSyncOperation(content); +}; + +module.exports.pitch = function(remainingRequest, precedingRequest, data) { + if (someCondition()) { + return 'module.exports = require(' + JSON.stringify('-!' + remainingRequest) + ');'; + } +}; +``` + +The steps above would be shortened to: + +``` diff +|- a-loader `pitch` + |- b-loader `pitch` returns a module +|- a-loader normal execution +``` + +See the [bundle-loader](https://github.com/webpack-contrib/bundle-loader) for a good example of how this process can be used in a more meaningful way. + + +## The Loader Context + +The loader context represents the properties that are available inside of a loader assigned to the `this` property. + +Given the following example this require call is used: +In `/abc/file.js`: + +``` js +require('./loader1?xyz!loader2!./resource?rrr'); +``` + + +### `this.version` + +__Loader API version.__ Currently `2`. This is useful for providing backwards compatibility. Using the version you can specify custom logic or fallbacks for breaking changes. + + +### `this.context` + +__The directory of the module.__ Can be used as context for resolving other stuff. + +In the example: `/abc` because `resource.js` is in this directory + + +### `this.rootContext` + +Starting with webpack 4, the formerly `this.options.context` is provided as `this.rootContext`. + + +### `this.request` + +The resolved request string. + +In the example: `"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"` + + +### `this.query` + +1. If the loader was configured with an [`options`](/configuration/module/#useentry) object, this will point to that object. +2. If the loader has no `options`, but was invoked with a query string, this will be a string starting with `?`. + +T> Use the [`getOptions` method](https://github.com/webpack/loader-utils#getoptions) from `loader-utils` to extract given loader options. + + +### `this.callback` + +A function that can be called synchronously or asynchronously in order to return multiple results. The expected arguments are: + +<!-- eslint-skip --> + +```js +this.callback( + err: Error | null, + content: string | Buffer, + sourceMap?: SourceMap, + meta?: any +); +``` + +1. The first argument must be an `Error` or `null` +2. The second argument a `string` or a [`Buffer`](https://nodejs.org/api/buffer.html). +3. Optional: The third argument must be a source map that is parsable by [this module](https://github.com/mozilla/source-map). +4. Optional: The fourth option, ignored by webpack, can be anything (e.g. some meta data). + +T> It can be useful to pass an abstract syntax tree (AST), like [`ESTree`](https://github.com/estree/estree), as the fourth argument (`meta`) to speed up the build time if you want to share common ASTs between loaders. + +In case this function is called, you should return undefined to avoid ambiguous loader results. + + +### `this.async` + +Tells the [loader-runner](https://github.com/webpack/loader-runner) that the loader intends to call back asynchronously. Returns `this.callback`. + + +### `this.data` + +A data object shared between the pitch and the normal phase. + + +### `this.cacheable` + +A function that sets the cacheable flag: + +``` typescript +cacheable(flag = true: boolean) +``` + +By default, loader results are flagged as cacheable. Call this method passing `false` to make the loader's result not cacheable. + +A cacheable loader must have a deterministic result, when inputs and dependencies haven't changed. This means the loader shouldn't have other dependencies than specified with `this.addDependency`. + + +### `this.loaders` + +An array of all the loaders. It is writeable in the pitch phase. + +<!-- eslint-skip --> + +```js +loaders = [{request: string, path: string, query: string, module: function}] +``` + +In the example: + +``` js +[ + { + request: '/abc/loader1.js?xyz', + path: '/abc/loader1.js', + query: '?xyz', + module: [Function] + }, + { + request: '/abc/node_modules/loader2/index.js', + path: '/abc/node_modules/loader2/index.js', + query: '', + module: [Function] + } +]; +``` + + +### `this.loaderIndex` + +The index in the loaders array of the current loader. + +In the example: in loader1: `0`, in loader2: `1` + + +### `this.resource` + +The resource part of the request, including query. + +In the example: `"/abc/resource.js?rrr"` + + +### `this.resourcePath` + +The resource file. + +In the example: `"/abc/resource.js"` + + +### `this.resourceQuery` + +The query of the resource. + +In the example: `"?rrr"` + + +### `this.target` + +Target of compilation. Passed from configuration options. + +Example values: `"web"`, `"node"` + + +### `this.webpack` + +This boolean is set to true when this is compiled by webpack. + +T> Loaders were originally designed to also work as Babel transforms. Therefore if you write a loader that works for both, you can use this property to know if there is access to additional loaderContext and webpack features. + + +### `this.sourceMap` + +Should a source map be generated. Since generating source maps can be an expensive task, you should check if source maps are actually requested. + + +### `this.emitWarning` + +``` typescript +emitWarning(warning: Error) +``` + +Emit a warning. + + +### `this.emitError` + +``` typescript +emitError(error: Error) +``` + +Emit an error. + + +### `this.loadModule` + +``` typescript +loadModule(request: string, callback: function(err, source, sourceMap, module)) +``` + +Resolves the given request to a module, applies all configured loaders and calls back with the generated source, the sourceMap and the module instance (usually an instance of [`NormalModule`](https://github.com/webpack/webpack/blob/master/lib/NormalModule.js)). Use this function if you need to know the source code of another module to generate the result. + + +### `this.resolve` + +``` typescript +resolve(context: string, request: string, callback: function(err, result: string)) +``` + +Resolve a request like a require expression. + + +### `this.addDependency` + +``` typescript +addDependency(file: string) +dependency(file: string) // shortcut +``` + +Adds a file as dependency of the loader result in order to make them watchable. For example, [`html-loader`](https://github.com/webpack-contrib/html-loader) uses this technique as it finds `src` and `src-set` attributes. Then, it sets the url's for those attributes as dependencies of the html file that is parsed. + + +### `this.addContextDependency` + +``` typescript +addContextDependency(directory: string) +``` + +Add a directory as dependency of the loader result. + + +### `this.clearDependencies` + +``` typescript +clearDependencies() +``` + +Remove all dependencies of the loader result. Even initial dependencies and these of other loaders. Consider using `pitch`. + + +### `this.emitFile` + +``` typescript +emitFile(name: string, content: Buffer|string, sourceMap: {...}) +``` + +Emit a file. This is webpack-specific. + + +### `this.fs` + +Access to the `compilation`'s `inputFileSystem` property. + + +## Deprecated context properties + +W> The usage of these properties is highly discouraged since we are planning to remove them from the context. They are still listed here for documentation purposes. + + +### `this.exec` + +``` typescript +exec(code: string, filename: string) +``` + +Execute some code fragment like a module. See [this comment](https://github.com/webpack/webpack.js.org/issues/1268#issuecomment-313513988) for a replacement method if needed. + + +### `this.resolveSync` + +``` typescript +resolveSync(context: string, request: string) -> string +``` + +Resolve a request like a require expression. + + +### `this.value` + +Pass values to the next loader. If you know what your result exports if executed as module, set this value here (as a only element array). + + +### `this.inputValue` + +Passed from the last loader. If you would execute the input argument as module, consider reading this variable for a shortcut (for performance). + + +### `this.options` + +W> The `options` property has been deprecated in webpack 3 and removed in webpack 4. + + +### `this.debug` + +A boolean flag. It is set when in debug mode. + + +### `this.minimize` + +Should the result be minimized. + + +### `this._compilation` + +Hacky access to the Compilation object of webpack. + + +### `this._compiler` + +Hacky access to the Compiler object of webpack. + + +### `this._module` + +Hacky access to the Module object being loaded. + + +# Module Variables + +This section covers all __variables__ available in code compiled with webpack. Modules will have access to certain data from the compilation process through `module` and other variables. + + +### `module.loaded` (NodeJS) + +This is `false` if the module is currently executing, and `true` if the sync execution has finished. + + +### `module.hot` (webpack-specific) + +Indicates whether or not [Hot Module Replacement](/concepts/hot-module-replacement) is enabled and provides an interface to the process. See the [HMR API page](/api/hot-module-replacement) for details. + + +### `module.id` (CommonJS) + +The ID of the current module. + +``` javascript +module.id === require.resolve('./file.js'); +``` + + +### `module.exports` (CommonJS) + +Defines the value that will be returned when a consumer makes a `require` call to the module (defaults to a new object). + +``` javascript +module.exports = function doSomething() { + // Do something... +}; +``` + +W> This CANNOT be used in an asynchronous function. + + +### `exports` (CommonJS) + +This variable is equal to default value of `module.exports` (i.e. an object). If `module.exports` gets overwritten, `exports` will no longer be exported. + +``` javascript +exports.someValue = 42; +exports.anObject = { + x: 123 +}; +exports.aFunction = function doSomething() { + // Do something +}; +``` + + +### `global` (NodeJS) + +See [node.js global](https://nodejs.org/api/globals.html#globals_global). + + +### `process` (NodeJS) + +See [node.js process](https://nodejs.org/api/process.html). + + +### `__dirname` (NodeJS) + +Depending on the config option `node.__dirname`: + +- `false`: Not defined +- `mock`: equal "/" +- `true`: [node.js __dirname](https://nodejs.org/api/globals.html#globals_dirname) + +If used inside a expression that is parsed by the Parser, the config option is treated as `true`. + + +### `__filename` (NodeJS) + +Depending on the config option `node.__filename`: + +- `false`: Not defined +- `mock`: equal "/index.js" +- `true`: [node.js __filename](https://nodejs.org/api/globals.html#globals_filename) + +If used inside a expression that is parsed by the Parser, the config option is treated as `true`. + + +### `__resourceQuery` (webpack-specific) + +The resource query of the current module. If the following `require` call were made, then the query string would be available in `file.js`. + +``` javascript +require('file.js?test'); +``` + +__file.js__ + +``` javascript +__resourceQuery === '?test'; +``` + + +### `__webpack_public_path__` (webpack-specific) + +Equals the config options `output.publicPath`. + + +### `__webpack_require__` (webpack-specific) + +The raw require function. This expression isn't parsed by the Parser for dependencies. + + +### `__webpack_chunk_load__` (webpack-specific) + +The internal chunk loading function. Takes two arguments: + +- `chunkId` The id for the chunk to load. +- `callback(require)` A callback function called once the chunk is loaded. + + +### `__webpack_modules__` (webpack-specific) + +Access to the internal object of all modules. + + +### `__webpack_hash__` (webpack-specific) + +This variable is only available with the `HotModuleReplacementPlugin` or the `ExtendedAPIPlugin`. It provides access to the hash of the compilation. + + +### `__non_webpack_require__` (webpack-specific) + +Generates a `require` function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available. + + +### `DEBUG` (webpack-specific) + +Equals the config option `debug`. + + +# Parser + +The `parser` instance, found in the `compiler`, is used to parse each module +being processed by webpack. The `parser` is yet another webpack class that +extends `tapable` and provides a variety of `tapable` hooks that can be used by +plugin authors to customize the parsing process. + +The `parser` is found within [module factories](/api/compiler-hooks/#normalmodulefactory) and therefore takes little +more work to access: + +``` js +compiler.hooks.normalModuleFactory.tap('MyPlugin', factory => { + factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => { + parser.hooks.someHook.tap(/* ... */); + }); +}); +``` + +As with the `compiler`, `tapAsync` and `tapPromise` may also be available +depending on the type of hook. + + +## Hooks + +The following lifecycle hooks are exposed by the `parser` and can be accessed +as such: + + +### evaluateTypeof + +`SyncBailHook` + +Evaluate the type of an identifier. + +Parameters: `expression` + + +### evaluate + +`SyncBailHook` + +Evaluate an expression. + +Parameters: `expression` + + +### evaluateIdentifier + +`SyncBailHook` + +Evaluate an identifier that is a free variable. + +Parameters: `expression` + + +### evaluateDefinedIdentifier + +`SyncBailHook` + +Evaluate an identifier that is a defined variable. + +Parameters: `expression` + + +### evaluateCallExpressionMember + +`SyncBailHook` + +Evaluate a call to a member function of a successfully evaluated expression. + +Parameters: `expression` `param` + + +### statement + +`SyncBailHook` + +General purpose hook that is called when parsing statements in a code fragment. + +Parameters: `statement` + + +### statementIf + +`SyncBailHook` + +... + +Parameters: `statement` + + +### label + +`SyncBailHook` + +... + +Parameters: `statement` + + +### import + +`SyncBailHook` + +... + +Parameters: `statement` `source` + + +### importSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `source` `exportName` `identifierName` + + +### export + +`SyncBailHook` + +... + +Parameters: `statement` + + +### exportImport + +`SyncBailHook` + +... + +Parameters: `statement` `source` + + +### exportDeclaration + +`SyncBailHook` + +... + +Parameters: `statement` `declaration` + + +### exportExpression + +`SyncBailHook` + +... + +Parameters: `statement` `declaration` + + +### exportSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `identifierName` `exportName` `index` + + +### exportImportSpecifier + +`SyncBailHook` + +... + +Parameters: `statement` `source` `identifierName` `exportName` `index` + + +### varDeclaration + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationLet + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationConst + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### varDeclarationVar + +`SyncBailHook` + +... + +Parameters: `declaration` + + +### canRename + +`SyncBailHook` + +... + +Parameters: `initExpression` + + +### rename + +`SyncBailHook` + +... + +Parameters: `initExpression` + + +### assigned + +`SyncBailHook` + +... + +Parameters: `expression` + + +### assign + +`SyncBailHook` + +... + +Parameters: `expression` + + +### typeof + +`SyncBailHook` + +... + +Parameters: `expression` + + +### call + +`SyncBailHook` + +... + +Parameters: `expression` + + +### callAnyMember + +`SyncBailHook` + +... + +Parameters: `expression` + + +### new + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expression + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expressionAnyMember + +`SyncBailHook` + +... + +Parameters: `expression` + + +### expressionConditionalOperator + +`SyncBailHook` + +... + +Parameters: `expression` + + +### program + +`SyncBailHook` + +Get access to the abstract syntax tree (AST) of a code fragment + +Parameters: `ast` `comments` diff --git a/src/content/concepts/_concepts_all.md b/src/content/concepts/_concepts_all.md new file mode 100644 index 000000000000..7ea61cfe8aaa --- /dev/null +++ b/src/content/concepts/_concepts_all.md @@ -0,0 +1,1086 @@ + + +# Concepts + +At its core, __webpack__ is a _static module bundler_ for modern JavaScript applications. When webpack processes your application, it internally builds a [dependency graph](/concepts/dependency-graph/) which maps every module your project needs and generates one or more _bundles_. + +T> Learn more about JavaScript modules and webpack modules [here](/concepts/modules). + +Since version 4.0.0, __webpack does not require a configuration file__ to bundle your project, nevertheless it is [incredibly configurable](/configuration) to better fit your needs. + +To get started you only need to understand its __Core Concepts__: + +- [Entry](#entry) +- [Output](#output) +- [Loaders](#loaders) +- [Plugins](#plugins) +- [Mode](#mode) +- [Browser Compatibility](#browser-compatibility) + +This document is intended to give a __high-level__ overview of these concepts, while providing links to detailed concept specific use cases. + +For a better understanding of the ideas behind module bundlers and how they work under the hood consult these resources: + +- [Manually Bundling an Application](https://www.youtube.com/watch?v=UNMkLHzofQI) +- [Live Coding a Simple Module Bundler](https://www.youtube.com/watch?v=Gc9-7PBqOC8) +- [Detailed Explanation of a Simple Module Bundler](https://github.com/ronami/minipack) + + +## Entry + +An __entry point__ indicates which module webpack should use to begin building out its internal [dependency graph](/concepts/dependency-graph/). webpack will figure out which other modules and libraries that entry point depends on (directly and indirectly). + +By default its value is `./src/index.js`, but you can specify a different (or multiple entry points) by configuring the __entry__ property in the [webpack configuration](/configuration). For example: + +__webpack.config.js__ + +``` js +module.exports = { + entry: './path/to/my/entry/file.js' +}; +``` + +T> Learn more in the [entry points](/concepts/entry-points) section. + + +## Output + +The __output__ property tells webpack where to emit the _bundles_ it creates and how to name these files. It defaults to `./dist/main.js` for the main output file and to the `./dist` folder for any other generated file. + +You can configure this part of the process by specifying an `output` field in your configuration: + +__webpack.config.js__ + +```javascript +const path = require('path'); + +module.exports = { + entry: './path/to/my/entry/file.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'my-first-webpack.bundle.js' + } +}; +``` + +In the example above, we use the `output.filename` and the `output.path` properties to tell webpack the name of our bundle and where we want it to be emitted to. In case you're wondering about the path module being imported at the top, it is a core [Node.js module](https://nodejs.org/api/modules.html) that gets used to manipulate file paths. + +T> The `output` property has [many more configurable features](/configuration/output) and if you like to know more about the concepts behind it, you can [read more in the output section](/concepts/output). + + +## Loaders + +Out of the box, webpack only understands JavaScript and JSON files. __Loaders__ allow webpack to process other types of files and convert them into valid [modules](/concepts/modules) that can be consumed by your application and added to the dependency graph. + +W> Note that the ability to `import` any type of module, e.g. `.css` files, is a feature specific to webpack and may not be supported by other bundlers or task runners. We feel this extension of the language is warranted as it allows developers to build a more accurate dependency graph. + +At a high level, __loaders__ have two properties in your webpack configuration: + +1. The `test` property identifies which file or files should be transformed. +2. The `use` property indicates which loader should be used to do the transforming. + +__webpack.config.js__ + +```javascript +const path = require('path'); + +module.exports = { + output: { + filename: 'my-first-webpack.bundle.js' + }, + module: { + rules: [ + { test: /\.txt$/, use: 'raw-loader' } + ] + } +}; +``` + +The configuration above has defined a `rules` property for a single module with two required properties: `test` and `use`. This tells webpack's compiler the following: + +> "Hey webpack compiler, when you come across a path that resolves to a '.txt' file inside of a `require()`/`import` statement, __use__ the `raw-loader` to transform it before you add it to the bundle." + +W> It is important to remember that when defining rules in your webpack config, you are defining them under `module.rules` and not `rules`. For your benefit, webpack will warn you if this is done incorrectly. + +You can check further customization when including loaders in the [loaders section](/concepts/loaders). + + +## Plugins + +While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables. + +T> Check out the [plugin interface](/api/plugins) and how to use it to extend webpacks capabilities. + +In order to use a plugin, you need to `require()` it and add it to the `plugins` array. Most plugins are customizable through options. Since you can use a plugin multiple times in a config for different purposes, you need to create an instance of it by calling it with the `new` operator. + +__webpack.config.js__ + +```javascript +const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm +const webpack = require('webpack'); //to access built-in plugins + +module.exports = { + module: { + rules: [ + { test: /\.txt$/, use: 'raw-loader' } + ] + }, + plugins: [ + new HtmlWebpackPlugin({template: './src/index.html'}) + ] +}; +``` + +In the example above, the `html-webpack-plugin` generates an HTML file for your application by injecting automatically all your generated bundles. + +T> There are many plugins that webpack provides out of the box! Check out the [list of plugins](/plugins). + +Using plugins in your webpack config is straightforward - however, there are many use cases that are worth further exploration. [Learn more about them here](/concepts/plugins). + + +## Mode + +By setting the `mode` parameter to either `development`, `production` or `none`, you can enable webpack's built-in optimizations that correspond to each environment. The default value is `production`. + +```javascript +module.exports = { + mode: 'production' +}; +``` + +Learn more about the [mode configuration here](/concepts/mode) and what optimizations take place on each value. + + +## Browser Compatibility + +webpack supports all browsers that are [ES5-compliant](https://kangax.github.io/compat-table/es5/) (IE8 and below are not supported). webpack needs `Promise` for `import()` and `require.ensure()`. If you want to support older browsers, you will need to [load a polyfill](/guides/shimming/) before using these expressions. + + +# Entry Points + +As mentioned in [Getting Started](/guides/getting-started/#using-a-configuration), there are multiple ways to define the `entry` property in your webpack configuration. We will show you the ways you __can__ configure the `entry` property, in addition to explaining why it may be useful to you. + + +## Single Entry (Shorthand) Syntax + +Usage: `entry: string|Array<string>` + +__webpack.config.js__ + +```javascript +module.exports = { + entry: './path/to/my/entry/file.js' +}; +``` + +The single entry syntax for the `entry` property is a shorthand for: + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + main: './path/to/my/entry/file.js' + } +}; +``` + +T> __What happens when you pass an array to `entry`?__ Passing an array of file paths to the `entry` property creates what is known as a __"multi-main entry"__. This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk". + +This is a great choice when you are looking to quickly setup a webpack configuration for an application or tool with one entry point (i.e., a library). However, there is not much flexibility in extending or scaling your configuration with this syntax. + + +## Object Syntax + +Usage: `entry: {[entryChunkName: string]: string|Array<string>}` + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + app: './src/app.js', + adminApp: './src/adminApp.js' + } +}; +``` + +The object syntax is more verbose. However, this is the most scalable way of defining entry/entries in your application. + +T> __"Scalable webpack configurations"__ are ones that can be reused and combined with other partial configurations. This is a popular technique used to separate concerns by environment, build target and runtime. They are then merged using specialized tools like [webpack-merge](https://github.com/survivejs/webpack-merge). + + +## Scenarios + +Below is a list of entry configurations and their real-world use cases: + +### Separate App and Vendor Entries + +T> In webpack version < 4 it was common to add vendors as separate entrypoint to compile it as separate file (in combination with the `CommonsChunkPlugin`). This is discouraged in webpack 4. Instead the `optimization.splitChunks` option takes care of separating vendors and app modules and creating a separate file. __Do not__ create a entry for vendors or other stuff which is not the starting point of execution. + +### Multi Page Application + +__webpack.config.js__ + +```javascript +module.exports = { + entry: { + pageOne: './src/pageOne/index.js', + pageTwo: './src/pageTwo/index.js', + pageThree: './src/pageThree/index.js' + } +}; +``` + +__What does this do?__ We are telling webpack that we would like 3 separate dependency graphs (like the above example). + +__Why?__ In a multi-page application, the server is going to fetch a new HTML document for you. The page reloads this new document and assets are redownloaded. However, this gives us the unique opportunity to do multiple things: + +- Use `optimization.splitChunks` to create bundles of shared application code between each page. Multi-page applications that reuse a lot of code/modules between entry points can greatly benefit from these techniques, as the amount of entry points increase. + +T> As a rule of thumb: for each HTML document use exactly one entry point. + + +# Output + +Configuring the `output` configuration options tells webpack how to write the compiled files to disk. Note that, while there can be multiple `entry` points, only one `output` configuration is specified. + + +## Usage + +The minimum requirements for the `output` property in your webpack config is to set its value to an object including the following thing: + +- A `filename` to use for the output file(s). + +__webpack.config.js__ + +```javascript +module.exports = { + output: { + filename: 'bundle.js', + } +}; +``` + +This configuration would output a single `bundle.js` file into the `dist` directory. + + +## Multiple Entry Points + +If your configuration creates more than a single "chunk" (as with multiple entry points or when using plugins like CommonsChunkPlugin), you should use [substitutions](/configuration/output#output-filename) to ensure that each file has a unique name. + +```javascript +module.exports = { + entry: { + app: './src/app.js', + search: './src/search.js' + }, + output: { + filename: '[name].js', + path: __dirname + '/dist' + } +}; + +// writes to disk: ./dist/app.js, ./dist/search.js +``` + + +## Advanced + +Here's a more complicated example of using a CDN and hashes for assets: + +__config.js__ + +```javascript +module.exports = { + //... + output: { + path: '/home/proj/cdn/assets/[hash]', + publicPath: 'http://cdn.example.com/assets/[hash]/' + } +}; +``` + +In cases where the eventual `publicPath` of output files isn't known at compile time, it can be left blank and set dynamically at runtime via the `__webpack_public_path__` variable in the entry point file: + +```javascript +__webpack_public_path__ = myRuntimePublicPath; + +// rest of your application entry +``` + + +# Loaders + +Loaders are transformations that are applied on the source code of a module. They allow you to pre-process files as you `import` or “load” them. Thus, loaders are kind of like “tasks” in other build tools and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript or inline images as data URLs. Loaders even allow you to do things like `import` CSS files directly from your JavaScript modules! + + +## Example + +For example, you can use loaders to tell webpack to load a CSS file or to convert TypeScript to JavaScript. To do this, you would start by installing the loaders you need: + +``` bash +npm install --save-dev css-loader +npm install --save-dev ts-loader +``` + +And then instruct webpack to use the [`css-loader`](/loaders/css-loader) for every `.css` file and the [`ts-loader`](https://github.com/TypeStrong/ts-loader) for all `.ts` files: + +__webpack.config.js__ + +``` js +module.exports = { + module: { + rules: [ + { test: /\.css$/, use: 'css-loader' }, + { test: /\.ts$/, use: 'ts-loader' } + ] + } +}; +``` + + +## Using Loaders + +There are three ways to use loaders in your application: + +- [Configuration](#configuration) (recommended): Specify them in your __webpack.config.js__ file. +- [Inline](#inline): Specify them explicitly in each `import` statement. +- [CLI](#cli): Specify them within a shell command. + + +### Configuration + +[`module.rules`](/configuration/module/#module-rules) allows you to specify several loaders within your webpack configuration. +This is a concise way to display loaders, and helps to maintain clean code. It also offers you a full overview of each respective loader. + +Loaders are evaluated/executed from right to left. In the example below execution starts with sass-loader, continues with css-loader and finally ends with style-loader. See ["Loader Features"](/concepts/loaders/#loader-features) for more information about loaders order. + +```js-with-links-with-details +module.exports = { + module: { + rules: [ + { + test: /\.css$/, + use: [ + { loader: ['style-loader'](/loaders/style-loader) }, + { + loader: ['css-loader'](/loaders/css-loader), + options: { + modules: true + } + }, + { loader: ['sass-loader'](/loaders/sass-loader) } + ] + } + ] + } +}; +``` + + +### Inline + +It's possible to specify loaders in an `import` statement, or any [equivalent "importing" method](/api/module-methods). Separate loaders from the resource with `!`. Each part is resolved relative to the current directory. + +```js +import Styles from 'style-loader!css-loader?modules!./styles.css'; +``` + +It's possible to override any loaders in the configuration by prefixing the entire rule with `!`. + +Options can be passed with a query parameter, e.g. `?key=value&foo=bar`, or a JSON object, e.g. `?{"key":"value","foo":"bar"}`. + +T> Use `module.rules` whenever possible, as this will reduce boilerplate in your source code and allow you to debug or locate a loader faster if something goes south. + + +### CLI + +You can also use loaders through the CLI: + +```sh +webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader' +``` + +This uses the `jade-loader` for `.jade` files, and the [`style-loader`](/loaders/style-loader) and [`css-loader`](/loaders/css-loader) for `.css` files. + + +## Loader Features + +- Loaders can be chained. Each loader in the chain applies transformations to the processed resource. A chain is executed in reverse order. The first loader passes its result (resource with applied transformations) to the next one, and so forth. Finally, webpack expects JavaScript to be returned by the last loader in the chain. +- Loaders can be synchronous or asynchronous. +- Loaders run in Node.js and can do everything that’s possible there. +- Loaders can be configured with an `options` object (using `query` parameters to set options is still supported but has been deprecated). +- Normal modules can export a loader in addition to the normal `main` via `package.json` with the `loader` field. +- Plugins can give loaders more features. +- Loaders can emit additional arbitrary files. + +Loaders allow more power in the JavaScript ecosystem through preprocessing +functions (loaders). Users now have more flexibility to include fine-grained logic such as compression, packaging, language translations and [more](/loaders). + + +## Resolving Loaders + +Loaders follow the standard [module resolution](/concepts/module-resolution/). In most cases it will be loaded from the [module path](/concepts/module-resolution/#module-paths) (think `npm install`, `node_modules`). + +A loader module is expected to export a function and be written in Node.js compatible JavaScript. They are most commonly managed with npm, but you can also have custom loaders as files within your application. By convention, loaders are usually named `xxx-loader` (e.g. `json-loader`). See ["How to Write a Loader?"](/development/how-to-write-a-loader) for more information. + + +# Mode + +Providing the `mode` configuration option tells webpack to use its built-in optimizations accordingly. + +`string` + +T> Possible values for `mode` are: `none`, `development` or `production`(default). + +## Usage + +Just provide the `mode` option in the config: + +```javascript +module.exports = { + mode: 'production' +}; +``` + + +or pass it as a [CLI](/api/cli/) argument: + +```bash +webpack --mode=production +``` + +The following string values are supported: + +Option | Description +--------------------- | ----------------------- +`development` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `development`. Enables `NamedChunksPlugin` and `NamedModulesPlugin`. +`production` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `production`. Enables `FlagDependencyUsagePlugin`, `FlagIncludedChunksPlugin`, `ModuleConcatenationPlugin`, `NoEmitOnErrorsPlugin`, `OccurrenceOrderPlugin`, `SideEffectsFlagPlugin` and `TerserPlugin`. +`none` | Opts out of any default optimization options + +If not set, webpack sets `production` as the default value for `mode`. The supported values for mode are: + +T> Please remember that setting `NODE_ENV` doesn't automatically set `mode`. + + +### Mode: development + + +```diff +// webpack.development.config.js +module.exports = { ++ mode: 'development' +- devtool: 'eval', +- cache: true, +- performance: { +- hints: false +- }, +- output: { +- pathinfo: true +- }, +- optimization: { +- namedModules: true, +- namedChunks: true, +- nodeEnv: 'development', +- flagIncludedChunks: false, +- occurrenceOrder: false, +- sideEffects: false, +- usedExports: false, +- concatenateModules: false, +- splitChunks: { +- hidePathInfo: false, +- minSize: 10000, +- maxAsyncRequests: Infinity, +- maxInitialRequests: Infinity, +- }, +- noEmitOnErrors: false, +- checkWasmTypes: false, +- minimize: false, +- }, +- plugins: [ +- new webpack.NamedModulesPlugin(), +- new webpack.NamedChunksPlugin(), +- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), +- ] +} +``` + + +### Mode: production + + +```diff +// webpack.production.config.js +module.exports = { ++ mode: 'production', +- performance: { +- hints: 'warning' +- }, +- output: { +- pathinfo: false +- }, +- optimization: { +- namedModules: false, +- namedChunks: false, +- nodeEnv: 'production', +- flagIncludedChunks: true, +- occurrenceOrder: true, +- sideEffects: true, +- usedExports: true, +- concatenateModules: true, +- splitChunks: { +- hidePathInfo: true, +- minSize: 30000, +- maxAsyncRequests: 5, +- maxInitialRequests: 3, +- }, +- noEmitOnErrors: true, +- checkWasmTypes: true, +- minimize: true, +- }, +- plugins: [ +- new TerserPlugin(/* ... */), +- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), +- new webpack.optimize.ModuleConcatenationPlugin(), +- new webpack.NoEmitOnErrorsPlugin() +- ] +} +``` + + +### Mode: none + + +```diff +// webpack.custom.config.js +module.exports = { ++ mode: 'none', +- performance: { +- hints: false +- }, +- optimization: { +- flagIncludedChunks: false, +- occurrenceOrder: false, +- sideEffects: false, +- usedExports: false, +- concatenateModules: false, +- splitChunks: { +- hidePathInfo: false, +- minSize: 10000, +- maxAsyncRequests: Infinity, +- maxInitialRequests: Infinity, +- }, +- noEmitOnErrors: false, +- checkWasmTypes: false, +- minimize: false, +- }, +- plugins: [] +} +``` + +If you want to change the behavior according to the __mode__ variable inside the _webpack.config.js_, you have to export a function instead of an object: + +```javascript +var config = { + entry: './app.js' + //... +}; + +module.exports = (env, argv) => { + + if (argv.mode === 'development') { + config.devtool = 'source-map'; + } + + if (argv.mode === 'production') { + //... + } + + return config; +}; +``` + + +# Plugins + +__Plugins__ are the [backbone](https://github.com/webpack/tapable) of webpack. webpack itself is built on the __same plugin system__ that you use in your webpack configuration! + +They also serve the purpose of doing __anything else__ that a [loader](/concepts/loaders) cannot do. + + +## Anatomy + +A webpack __plugin__ is a JavaScript object that has an [`apply`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) method. This `apply` method is called by the webpack compiler, giving access to the __entire__ compilation lifecycle. + +__ConsoleLogOnBuildWebpackPlugin.js__ + +```javascript +const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; + +class ConsoleLogOnBuildWebpackPlugin { + apply(compiler) { + compiler.hooks.run.tap(pluginName, compilation => { + console.log('The webpack build process is starting!!!'); + }); + } +} +``` + +The first parameter of the tap method of the compiler hook should be a camelized version of the plugin name. It is advisable to use a constant for this so it can be reused in all hooks. + +## Usage + +Since __plugins__ can take arguments/options, you must pass a `new` instance to the `plugins` property in your webpack configuration. + +Depending on how you are using webpack, there are multiple ways to use plugins. + + +### Configuration + +__webpack.config.js__ + +```javascript +const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm +const webpack = require('webpack'); //to access built-in plugins +const path = require('path'); + +module.exports = { + entry: './path/to/my/entry/file.js', + output: { + filename: 'my-first-webpack.bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.(js|jsx)$/, + use: 'babel-loader' + } + ] + }, + plugins: [ + new webpack.ProgressPlugin(), + new HtmlWebpackPlugin({template: './src/index.html'}) + ] +}; +``` + + +### Node API + +When using the Node API, you can also pass plugins via the `plugins` property in the configuration. + +__some-node-script.js__ + +```javascript +const webpack = require('webpack'); //to access webpack runtime +const configuration = require('./webpack.config.js'); + +let compiler = webpack(configuration); + +new webpack.ProgressPlugin().apply(compiler); + +compiler.run(function(err, stats) { + // ... +}); +``` + +T> Did you know: The example seen above is extremely similar to the [webpack runtime itself!](https://github.com/webpack/webpack/blob/e7087ffeda7fa37dfe2ca70b5593c6e899629a2c/bin/webpack.js#L290-L292) There are lots of great usage examples hiding in the [webpack source code](https://github.com/webpack/webpack) that you can apply to your own configurations and scripts! + + +# Configuration + +You may have noticed that few webpack configurations look exactly alike. This is because __webpack's configuration file is a JavaScript file that exports a webpack [configuration](/configuration/).__ This configuration is then processed by webpack based upon its defined properties. + +Because it's a standard Node.js CommonJS module, you __can do the following__: + +- import other files via `require(...)` +- use utilities on npm via `require(...)` +- use JavaScript control flow expressions i. e. the `?:` operator +- use constants or variables for often used values +- write and execute functions to generate a part of the configuration + +Use these features when appropriate. + +While they are technically feasible, __the following practices should be avoided__: + +- Access CLI arguments, when using the webpack CLI (instead write your own CLI, or [use `--env`](/configuration/configuration-types/)) +- Export non-deterministic values (calling webpack twice should result in the same output files) +- Write long configurations (instead split the configuration into multiple files) + +T> The most important part to take away from this document is that there are many different ways to format and style your webpack configuration. The key is to stick with something consistent that you and your team can understand and maintain. + +The examples below describe how webpack's configuration can be both expressive and configurable because _it is code_: + +## Simple Configuration + +__webpack.config.js__ + +```javascript +var path = require('path'); + +module.exports = { + mode: 'development', + entry: './foo.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'foo.bundle.js' + } +}; +``` + +_See_: [Configuration section](/configuration/) for the all supported configuration options + +## Multiple Targets + +Along with exporting a single configuration as an object, [function](/configuration/configuration-types/#exporting-a-function) or [Promise](/configuration/configuration-types/#exporting-a-promise), you can export multiple configurations. + +_See_: [Exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) + +## Using other Configuration Languages + +webpack accepts configuration files written in multiple programming and data languages. + +_See_: [Configuration Languages](/configuration/configuration-languages/) + + +# Modules + +In [modular programming](https://en.wikipedia.org/wiki/Modular_programming), developers break programs up into discrete chunks of functionality called a _module_. + +Each module has a smaller surface area than a full program, making verification, debugging, and testing trivial. +Well-written _modules_ provide solid abstractions and encapsulation boundaries, so that each module has a coherent design and a clear purpose within the overall application. + +Node.js has supported modular programming almost since its inception. +On the web, however, support for _modules_ has been slow to arrive. +Multiple tools exist that support modular JavaScript on the web, with a variety of benefits and limitations. +webpack builds on lessons learned from these systems and applies the concept of _modules_ to any file in your project. + +## What is a webpack Module + +In contrast to [Node.js modules](https://nodejs.org/api/modules.html), webpack _modules_ can express their _dependencies_ in a variety of ways. A few examples are: + +- An [ES2015 `import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) statement +- A [CommonJS](http://www.commonjs.org/specs/modules/1.0/) `require()` statement +- An [AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md) `define` and `require` statement +- An [`@import` statement](https://developer.mozilla.org/en-US/docs/Web/CSS/@import) inside of a css/sass/less file. +- An image url in a stylesheet (`url(...)`) or html (`<img src=...>`) file. + +T> webpack 1 requires a specific loader to convert ES2015 `import`, however this is possible out of the box via webpack 2 + +## Supported Module Types + +webpack supports modules written in a variety of languages and preprocessors, via _loaders_. _Loaders_ describe to webpack __how__ to process non-JavaScript _modules_ and include these _dependencies_ into your _bundles_. +The webpack community has built _loaders_ for a wide variety of popular languages and language processors, including: + +- [CoffeeScript](http://coffeescript.org) +- [TypeScript](https://www.typescriptlang.org) +- [ESNext (Babel)](https://babeljs.io) +- [Sass](http://sass-lang.com) +- [Less](http://lesscss.org) +- [Stylus](http://stylus-lang.com) + +And many others! Overall, webpack provides a powerful and rich API for customization that allows one to use webpack for __any stack__, while staying __non-opinionated__ about your development, testing, and production workflows. + +For a full list, see [__the list of loaders__](/loaders) or [__write your own__](/api/loaders). + + +# Why webpack + +To understand why you should use webpack let's do a recap of how we used JavaScript on the web before bundlers were a thing. + +There are two ways to run JavaScript in a browser. First, include a script for each functionality you want to implement, the issue is that the solution is hard to scale as loading too many scripts causes a network bottleneck. The other alternative is to load a big .js file containing all your project code, but this results in an unmaintainable scripts that causes problems in scope, size, readability, fragility and monolith files. + + +## IIFE's - Immediately invoked function expressions + +IIFEs solve scoping issues for large projects. When script files are wrapped by an IIFE, you can safely concatenate or safely combine files without concern of scope collision. + +This lead to tools like Make, Gulp, Grunt, Broccoli or Brunch. These tools are known as task runners and they are used, among other purposes, to concatenate all your project files together in order to solve some of the issues mentioned before. + +However, anytime you want to change one file you have to rebuild the whole thing. Concatenating makes it trivial to reuse scripts across files and makes build optimizations more difficult to implement. How do you even know what code is being used and which is not? + +If you are only using one function from lodash or one date utility from moment.js you are actually adding the entire library and just squishing it together. How do you treeshake the dependencies on your code? Also, lazy loading chunks of code can be hard to achieve at scale and requires a lot of manual work from the developer. + + +## Birth of JavaScript Modules happened thanks to Node.js + +webpack runs on Node.js, a JavaScript runtime that can be used in computers and servers outside a browser environment. + +When Node.js was released a new era started, and it came with new challenges. Now that JavaScript is not running in a browser, how are Node applications supposed to load new chunks of code? There are no html files and script tags that can be added to it. + +CommonJS came out and introduced `require`, which allows you to load and use a module in the current file. This solves scope issues out of the box and which code is used becomes clear since we need to import each module that we are going to need. + + +## npm + Node.js + modules -- mass distribution + +JavaScript is taking over the world as a language, as a platform and as a way to rapidly develop and create fast running applications. + +But there is no browser support for CommonJS. There are no [live bindings](https://medium.com/webpack/the-state-of-javascript-modules-4636d1774358). There are problems with circular references. Sync module resolution loader is slow. While CommonJS was a great solution for Node.js projects, browsers didn't support modules. That's when bundlers and tools like Browserify, RequireJS and SystemJS were created to solve this limitation making it possible to write CommonJS modules that run in a browser. + + +## ESM - ECMAScript Modules + +The good news for web projects is that modules are becoming an official feature in ECMAScript standard, though browser support is still short and early implementations show that bundling is still faster and recommended today. + + +## Wouldn't it be nice… + +...to have something that will not only let us write modules but also support any module format (at least until we get to ESM) and that can handle resources and assets at the same time? + +This is why webpack exists. It's a tool that not only let's you bundle your JavaScript applications, supporting both ESM and CommonJS, but can be extended to support all different kinds of assets like images, fonts and stylesheets. + +webpack cares a lot about performance and it's always adding and improving features like async chunk loading and prefetching to help you deliver the best possible version of your project to the user, always caring about loading times and performance. + + +# Module Resolution + +A resolver is a library which helps in locating a module by its absolute path. +A module can be required as a dependency from another module as: + +```js +import foo from 'path/to/module'; +// or +require('path/to/module'); +``` + +The dependency module can be from the application code or a third party library. The resolver helps +webpack find the module code that needs to be included in the bundle for every such `require`/`import` statement. +webpack uses [enhanced-resolve](https://github.com/webpack/enhanced-resolve) to resolve file paths while bundling modules. + + +## Resolving rules in webpack + +Using `enhanced-resolve`, webpack can resolve three kinds of file paths: + + +### Absolute paths + +```js +import '/home/me/file'; + +import 'C:\\Users\\me\\file'; +``` + +Since we already have the absolute path to the file, no further resolution is required. + + +### Relative paths + +```js +import '../src/file1'; +import './file2'; +``` + +In this case, the directory of the resource file where the `import` or `require` occurs is taken to be the context directory. The relative path specified in the `import/require` is joined to this context path to produce the absolute path to the module. + + +### Module paths + +```js +import 'module'; +import 'module/lib/file'; +``` + +Modules are searched for inside all directories specified in [`resolve.modules`](/configuration/resolve/#resolve-modules). +You can replace the original module path by an alternate path by creating an alias for it using [`resolve.alias`](/configuration/resolve/#resolve-alias) configuration option. + +Once the path is resolved based on the above rule, the resolver checks to see if the path points to a file or a directory. If the path points to a file: + +- If the path has a file extension, then the file is bundled straightaway. +- Otherwise, the file extension is resolved using the [`resolve.extensions`](/configuration/resolve/#resolve-extensions) option, which tells the resolver which extensions (eg - `.js`, `.jsx`) are acceptable for resolution. + +If the path points to a folder, then the following steps are taken to find the right file with the right extension: + +- If the folder contains a `package.json` file, then fields specified in [`resolve.mainFields`](/configuration/resolve/#resolve-mainfields) configuration option are looked up in order, and the first such field in `package.json` determines the file path. +- If there is no `package.json` or if the main fields do not return a valid path, file names specified in the [`resolve.mainFiles`](/configuration/resolve/#resolve-mainfiles) configuration option are looked for in order, to see if a matching filename exists in the imported/required directory . +- The file extension is then resolved in a similar way using the `resolve.extensions` option. + +webpack provides reasonable [defaults](/configuration/resolve) for these options depending on your build target. + + +## Resolving Loaders + +This follows the same rules as those specified for file resolution. But the [`resolveLoader`](/configuration/resolve/#resolveloader) configuration option can be used to have separate resolution rules for loaders. + + +## Caching + +Every filesystem access is cached, so that multiple parallel or serial requests to the same file occur faster. In [watch mode](/configuration/watch/#watch), only modified files are evicted from the cache. If watch mode is off, then the cache gets purged before every compilation. + + +See [Resolve API](/configuration/resolve) to learn more on the configuration options mentioned above. + + +# Dependency Graph + +Any time one file depends on another, webpack treats this as a _dependency_. This allows webpack to take non-code assets, such as images or web fonts, and also provide them as _dependencies_ for your application. + +When webpack processes your application, it starts from a list of modules defined on the command line or in its config file. +Starting from these [_entry points_](/concepts/entry-points/), webpack recursively builds a _dependency graph_ that includes every module your application needs, then bundles all of those modules into a small number of _bundles_ - often, just one - to be loaded by the browser. + +T> Bundling your application is especially powerful for _HTTP/1.1_ clients, as it minimizes the number of times your app has to wait while the browser starts a new request. For _HTTP/2_, you can also use [Code Splitting](/guides/code-splitting/) to achieve best results. + + +# Targets + +Because JavaScript can be written for both server and browser, webpack offers multiple deployment _targets_ that you can set in your webpack [configuration](/configuration). + +W> The webpack `target` property is not to be confused with the `output.libraryTarget` property. For more information see [our guide](/concepts/output/) on the `output` property. + +## Usage + +To set the `target` property, you simply set the target value in your webpack config: + +__webpack.config.js__ + +```javascript +module.exports = { + target: 'node' +}; +``` + +In the example above, using `node` webpack will compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks and not touch any built in modules like `fs` or `path`). + +Each _target_ has a variety of deployment/environment specific additions, support to fit its needs. See what [targets are available](/configuration/target/). + +?>Further expansion for other popular target values + +## Multiple Targets + +Although webpack does __not__ support multiple strings being passed into the `target` property, you can create an isomorphic library by bundling two separate configurations: + +__webpack.config.js__ + +```javascript +const path = require('path'); +const serverConfig = { + target: 'node', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'lib.node.js' + } + //… +}; + +const clientConfig = { + target: 'web', // <=== can be omitted as default is 'web' + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'lib.js' + } + //… +}; + +module.exports = [ serverConfig, clientConfig ]; +``` + +The example above will create a `lib.js` and `lib.node.js` file in your `dist` folder. + +## Resources + +As seen from the options above there are multiple different deployment _targets_ that you can choose from. Below is a list of examples, and resources that you can refer to. + +- __[compare-webpack-target-bundles](https://github.com/TheLarkInn/compare-webpack-target-bundles)__: A great resource for testing and viewing different webpack _targets_. Also great for bug reporting. +- __[Boilerplate of Electron-React Application](https://github.com/chentsulin/electron-react-boilerplate)__: A good example of a build process for electron's main process and renderer process. + +?> Need to find up to date examples of these webpack targets being used in live code or boilerplates. + + +# The Manifest + +In a typical application or site built with webpack, there are three main types of code: + +1. The source code you, and maybe your team, have written. +2. Any third-party library or "vendor" code your source is dependent on. +3. A webpack runtime and __manifest__ that conducts the interaction of all modules. + +This article will focus on the last of these three parts, the runtime and in particular the manifest. + + +## Runtime + +The runtime, along with the manifest data, is basically all the code webpack needs to connect your modularized application while it's running in the browser. It contains the loading and resolving logic needed to connect your modules as they interact. This includes connecting modules that have already been loaded into the browser as well as logic to lazy-load the ones that haven't. + + +## Manifest + +Once your application hits the browser in the form of `index.html` file, some bundles and a variety of other assets required by your application must be loaded and linked somehow. That `/src` directory you meticulously laid out is now bundled, minified and maybe even split into smaller chunks for lazy-loading by webpack's [`optimization`](/configuration/optimization/). So how does webpack manage the interaction between all of your required modules? This is where the manifest data comes in... + +As the compiler enters, resolves, and maps out your application, it keeps detailed notes on all your modules. This collection of data is called the "Manifest" and it's what the runtime will use to resolve and load modules once they've been bundled and shipped to the browser. No matter which [module syntax](/api/module-methods) you have chosen, those `import` or `require` statements have now become `__webpack_require__` methods that point to module identifiers. Using the data in the manifest, the runtime will be able to find out where to retrieve the modules behind the identifiers. + + +## The Problem + +So now you have a little bit of insight about how webpack works behind the scenes. "But, how does this affect me?", you might ask. The simple answer is that most of the time it doesn't. The runtime will do its thing, utilizing the manifest, and everything will appear to just magically work once your application hits the browser. However, if you decide to improve your projects performance by utilizing browser caching, this process will all of a sudden become an important thing to understand. + +By using content hashes within your bundle file names, you can indicate to the browser when the contents of a file has changed thus invalidating the cache. Once you start doing this though, you'll immediately notice some funny behavior. Certain hashes change even when their contents apparently do not. This is caused by the injection of the runtime and manifest which changes every build. + +See [the manifest section](/guides/output-management/#the-manifest) of our _Output management_ guide to learn how to extract the manifest, and read the guides below to learn more about the intricacies of long term caching. + + +# Hot Module Replacement + +Hot Module Replacement (HMR) exchanges, adds, or removes [modules](/concepts/modules/) while an application is running, without a full reload. This can significantly speed up development in a few ways: + +- Retain application state which is lost during a full reload. +- Save valuable development time by only updating what's changed. +- Modifications made to CSS/JS in the source code results in an instant browser update which is almost comparable to changing styles directly in the browser's dev tools. + + +## How It Works + +Let's go through some different viewpoints to understand exactly how HMR works... + +### In the Application + +The following steps allow modules to be swapped in and out of an application: + +1. The application asks the HMR runtime to check for updates. +2. The runtime asynchronously downloads the updates and notifies the application. +3. The application then asks the runtime to apply the updates. +4. The runtime synchronously applies the updates. + +You can set up HMR so that this process happens automatically, or you can choose to require user interaction for updates to occur. + + +### In the Compiler + +In addition to normal assets, the compiler needs to emit an "update" to allow updating from previous version to the new version. The "update" consists of two parts: + +1. The updated [manifest](/concepts/manifest) (JSON) +2. One or more updated chunks (JavaScript) + +The manifest contains the new compilation hash and a list of all updated chunks. Each of these chunks contains the new code for all updated modules (or a flag indicating that the module was removed). + +The compiler ensures that module IDs and chunk IDs are consistent between these builds. It typically stores these IDs in memory (e.g. with [webpack-dev-server](/configuration/dev-server/)), but it's also possible to store them in a JSON file. + + +### In a Module + +HMR is an opt-in feature that only affects modules containing HMR code. One example would be patching styling through the [`style-loader`](https://github.com/webpack-contrib/style-loader). In order for patching to work, the `style-loader` implements the HMR interface; when it receives an update through HMR, it replaces the old styles with the new ones. + +Similarly, when implementing the HMR interface in a module, you can describe what should happen when the module is updated. However, in most cases, it's not mandatory to write HMR code in every module. If a module has no HMR handlers, the update bubbles up. This means that a single handler can update a complete module tree. If a single module from the tree is updated, the entire set of dependencies is reloaded. + +See the [HMR API page](/api/hot-module-replacement) for details on the `module.hot` interface. + + +### In the Runtime + +Here things get a bit more technical... if you're not interested in the internals, feel free to jump to the [HMR API page](/api/hot-module-replacement) or [HMR guide](/guides/hot-module-replacement). + +For the module system runtime, additional code is emitted to track module `parents` and `children`. On the management side, the runtime supports two methods: `check` and `apply`. + +A `check` makes an HTTP request to the update manifest. If this request fails, there is no update available. If it succeeds, the list of updated chunks is compared to the list of currently loaded chunks. For each loaded chunk, the corresponding update chunk is downloaded. All module updates are stored in the runtime. When all update chunks have been downloaded and are ready to be applied, the runtime switches into the `ready` state. + +The `apply` method flags all updated modules as invalid. For each invalid module, there needs to be an update handler in the module or in its parent(s). Otherwise, the invalid flag bubbles up and invalidates parent(s) as well. Each bubble continues until the app's entry point or a module with an update handler is reached (whichever comes first). If it bubbles up from an entry point, the process fails. + +Afterwards, all invalid modules are disposed (via the dispose handler) and unloaded. The current hash is then updated and all `accept` handlers are called. The runtime switches back to the `idle` state and everything continues as normal. + + +## Get Started + +HMR can be used in development as a LiveReload replacement. [webpack-dev-server](/configuration/dev-server/) supports a `hot` mode in which it tries to update with HMR before trying to reload the whole page. See the [Hot Module Replacement guide](/guides/hot-module-replacement) for details. + +T> As with many other features, webpack's power lies in its customizability. There are _many_ ways of configuring HMR depending on the needs of a particular project. However, for most purposes, `webpack-dev-server` is a good fit and will allow you to get started with HMR quickly. diff --git a/src/content/configuration/_configuration_all.md b/src/content/configuration/_configuration_all.md new file mode 100644 index 000000000000..a1e52dc062a1 --- /dev/null +++ b/src/content/configuration/_configuration_all.md @@ -0,0 +1,5315 @@ + + +# Configuration + +Out of the box, webpack won't require you to use a configuration file. However, it will assume the entry point of your project is `src/index` and will output the result in `dist/main.js` minified and optimized for production. + +Usually your projects will need to extend this functionality, for this you can create a `webpack.config.js` file in the root folder and webpack will automatically use it. + +All the available configuration options are specified below. + +T> New to webpack? Check out our guide to some of webpack's [core concepts](/concepts/) to get started! + +## Options + +Click on the name of each option in the configuration code below to jump to the detailed documentation. Also note that the items with arrows can be expanded to show more examples and, in some cases, more advanced configuration. + +W> Notice that throughout the configuration we use Node's built-in [path module](https://nodejs.org/api/path.html) and prefix it with the [__dirname](https://nodejs.org/docs/latest/api/globals.html#globals_dirname) global. This prevents file path issues between operating systems and allows relative paths to work as expected. See [this section](https://nodejs.org/api/path.html#path_windows_vs_posix) for more info on POSIX vs. Windows paths. + +__webpack.config.js__ + +```js-with-links-with-details +const path = require('path'); + +module.exports = { + <details><summary>[mode](/concepts/mode): "production", // "production" | "development" | "none"</summary> + [mode](/concepts/mode): "production", // enable many optimizations for production builds + [mode](/concepts/mode): "development", // enabled useful tools for development + [mode](/concepts/mode): "none", // no defaults + </details> + // Chosen mode tells webpack to use its built-in optimizations accordingly. + <details><summary>[entry](/configuration/entry-context#entry): "./app/entry", // string | object | array</summary> + [entry](/configuration/entry-context#entry): ["./app/entry1", "./app/entry2"], + [entry](/configuration/entry-context#entry): { + a: "./app/entry-a", + b: ["./app/entry-b1", "./app/entry-b2"] + }, + </details> + // defaults to './src' + // Here the application starts executing + // and webpack starts bundling + [output](/configuration/output): { + // options related to how webpack emits results + [path](/configuration/output#output-path): path.resolve(__dirname, "dist"), // string + // the target directory for all output files + // must be an absolute path (use the Node.js path module) + <details><summary>[filename](/configuration/output#output-filename): "bundle.js", // string</summary> + [filename](/configuration/output#output-filename): "[name].js", // for multiple entry points + [filename](/configuration/output#output-filename): "[chunkhash].js", // for [long term caching](/guides/caching) + </details> + // the filename template for entry chunks + <details><summary>[publicPath](/configuration/output#output-publicpath): "/assets/", // string</summary> + [publicPath](/configuration/output#output-publicpath): "", + [publicPath](/configuration/output#output-publicpath): "https://cdn.example.com/", + </details> + // the url to the output directory resolved relative to the HTML page + [library](/configuration/output#output-library): "MyLibrary", // string, + // the name of the exported library + <details><summary>[libraryTarget](/configuration/output#output-librarytarget): "umd", // universal module definition</summary> + [libraryTarget](/configuration/output#output-librarytarget): "umd2", // universal module definition + [libraryTarget](/configuration/output#output-librarytarget): "commonjs2", // exported with module.exports + [libraryTarget](/configuration/output#output-librarytarget): "commonjs", // exported as properties to exports + [libraryTarget](/configuration/output#output-librarytarget): "amd", // defined with AMD defined method + [libraryTarget](/configuration/output#output-librarytarget): "this", // property set on this + [libraryTarget](/configuration/output#output-librarytarget): "var", // variable defined in root scope + [libraryTarget](/configuration/output#output-librarytarget): "assign", // blind assignment + [libraryTarget](/configuration/output#output-librarytarget): "window", // property set to window object + [libraryTarget](/configuration/output#output-librarytarget): "global", // property set to global object + [libraryTarget](/configuration/output#output-librarytarget): "jsonp", // jsonp wrapper + </details> + // the type of the exported library + <details><summary>/* Advanced output configuration (click to show) */</summary> + [pathinfo](/configuration/output#output-pathinfo): true, // boolean + // include useful path info about modules, exports, requests, etc. into the generated cod + [chunkFilename](/configuration/output#output-chunkfilename): "[id].js", + [chunkFilename](/configuration/output#output-chunkfilename): "[chunkhash].js", // for [long term caching](/guides/caching) + // the filename template for additional chunks + [jsonpFunction](/configuration/output#output-jsonpfunction): "myWebpackJsonp", // string + // name of the JSONP function used to load chunks + [sourceMapFilename](/configuration/output#output-sourcemapfilename): "[file].map", // string + [sourceMapFilename](/configuration/output#output-sourcemapfilename): "sourcemaps/[file].map", // string + // the filename template of the source map location + [devtoolModuleFilenameTemplate](/configuration/output#output-devtoolmodulefilenametemplate): "webpack:///[resource-path]", // string + // the name template for modules in a devtool + [devtoolFallbackModuleFilenameTemplate](/configuration/output#output-devtoolfallbackmodulefilenametemplate): "webpack:///[resource-path]?[hash]", // string + // the name template for modules in a devtool (used for conflicts) + [umdNamedDefine](/configuration/output#output-umdnameddefine): true, // boolean + // use a named AMD module in UMD library + [crossOriginLoading](/configuration/output#output-crossoriginloading): "use-credentials", // enum + [crossOriginLoading](/configuration/output#output-crossoriginloading): "anonymous", + [crossOriginLoading](/configuration/output#output-crossoriginloading): false, + // specifies how cross origin request are issued by the runtime + <details><summary>/* Expert output configuration (on own risk) */</summary> + [devtoolLineToLine](/configuration/output#output-devtoollinetoline): { + test: /\.jsx$/ + }, + // use a simple 1:1 mapped SourceMaps for these modules (faster) + [hotUpdateMainFilename](/configuration/output#output-hotupdatemainfilename): "[hash].hot-update.json", // string + // filename template for HMR manifest + [hotUpdateChunkFilename](/configuration/output#output-hotupdatechunkfilename): "[id].[hash].hot-update.js", // string + // filename template for HMR chunks + [sourcePrefix](/configuration/output#output-sourceprefix): "\t", // string + // prefix module sources in bundle for better readablitity + </details> + </details> + }, + [module](/configuration/module): { + // configuration regarding modules + [rules](/configuration/module#module-rules): [ + // rules for modules (configure loaders, parser options, etc.) + { + [test](/configuration/module#rule-test): /\.jsx?$/, + [include](/configuration/module#rule-include): [ + path.resolve(__dirname, "app") + ], + [exclude](/configuration/module#rule-exclude): [ + path.resolve(__dirname, "app/demo-files") + ], + // these are matching conditions, each accepting a regular expression or string + // test and include have the same behavior, both must be matched + // exclude must not be matched (takes preference over test and include) + // Best practices: + // - Use RegExp only in test and for filename matching + // - Use arrays of absolute paths in include and exclude + // - Try to avoid exclude and prefer include + [issuer](/configuration/module#rule-issuer): { test, include, exclude }, + // conditions for the issuer (the origin of the import) + [enforce](/configuration/module#rule-enforce): "pre", + [enforce](/configuration/module#rule-enforce): "post", + // flags to apply these rules, even if they are overridden (advanced option) + [loader](/configuration/module#rule-loader): "babel-loader", + // the loader which should be applied, it'll be resolved relative to the context + // -loader suffix is no longer optional in webpack2 for clarity reasons + // see [webpack 1 upgrade guide](/migrate/3/#automatic-loader-module-name-extension-removed) + [options](/configuration/module#rule-options-rule-query): { + presets: ["es2015"] + }, + // options for the loader + }, + { + [test](/configuration/module#rule-test): /\.html$/, + [use](/configuration/module#rule-use): [ + // apply multiple loaders and options + "htmllint-loader", + { + loader: "html-loader", + options: { + /* ... */ + } + } + ] + }, + { [oneOf](/configuration/module#rule-oneof): [ /* rules */ ] }, + // only use one of these nested rules + { [rules](/configuration/module#rule-rules): [ /* rules */ ] }, + // use all of these nested rules (combine with conditions to be useful) + { [resource](/configuration/module#rule-resource): { [and](/configuration/module#condition): [ /* conditions */ ] } }, + // matches only if all conditions are matched + { [resource](/configuration/module#rule-resource): { [or](/configuration/module#condition): [ /* conditions */ ] } }, + { [resource](/configuration/module#rule-resource): [ /* conditions */ ] }, + // matches if any condition is matched (default for arrays) + { [resource](/configuration/module#rule-resource): { [not](/configuration/module#condition): /* condition */ } } + // matches if the condition is not matched + ], + <details><summary>/* Advanced module configuration (click to show) */</summary> + [noParse](/configuration/module#module-noparse): [ + /special-library\.js$/ + ], + // do not parse this module + unknownContextRequest: ".", + unknownContextRecursive: true, + unknownContextRegExp: /^\.\/.*$/, + unknownContextCritical: true, + exprContextRequest: ".", + exprContextRegExp: /^\.\/.*$/, + exprContextRecursive: true, + exprContextCritical: true, + wrappedContextRegExp: /.*/, + wrappedContextRecursive: true, + wrappedContextCritical: false, + // specifies default behavior for dynamic requests + </details> + }, + [resolve](/configuration/resolve): { + // options for resolving module requests + // (does not apply to resolving to loaders) + [modules](/configuration/resolve#resolve-modules): [ + "node_modules", + path.resolve(__dirname, "app") + ], + // directories where to look for modules + [extensions](/configuration/resolve#resolve-extensions): [".js", ".json", ".jsx", ".css"], + // extensions that are used + [alias](/configuration/resolve#resolve-alias): { + // a list of module name aliases + "module": "new-module", + // alias "module" -> "new-module" and "module/path/file" -> "new-module/path/file" + "only-module$": "new-module", + // alias "only-module" -> "new-module", but not "only-module/path/file" -> "new-module/path/file" + "module": path.resolve(__dirname, "app/third/module.js"), + // alias "module" -> "./app/third/module.js" and "module/file" results in error + // modules aliases are imported relative to the current context + }, + <details><summary>/* alternative alias syntax (click to show) */</summary> + [alias](/configuration/resolve#resolve-alias): [ + { + name: "module", + // the old request + alias: "new-module", + // the new request + onlyModule: true + // if true only "module" is aliased + // if false "module/inner/path" is also aliased + } + ], + </details> + <details><summary>/* Advanced resolve configuration (click to show) */</summary> + [symlinks](/configuration/resolve#resolve-symlinks): true, + // follow symlinks to new location + [descriptionFiles](/configuration/resolve#resolve-descriptionfiles): ["package.json"], + // files that are read for package description + [mainFields](/configuration/resolve#resolve-mainfields): ["main"], + // properties that are read from description file + // when a folder is requested + [aliasFields](/configuration/resolve#resolve-aliasfields): ["browser"], + // properties that are read from description file + // to alias requests in this package + [enforceExtension](/configuration/resolve#resolve-enforceextension): false, + // if true request must not include an extensions + // if false request may already include an extension + [moduleExtensions](/configuration/resolve#resolveloader-moduleextensions): ["-module"], + [enforceModuleExtension](/configuration/resolve#resolve-enforcemoduleextension): false, + // like extensions/enforceExtension but for module names instead of files + [unsafeCache](/configuration/resolve#resolve-unsafecache): true, + [unsafeCache](/configuration/resolve#resolve-unsafecache): {}, + // enables caching for resolved requests + // this is unsafe as folder structure may change + // but performance improvement is really big + [cachePredicate](/configuration/resolve#resolve-cachepredicate): (path, request) => true, + // predicate function which selects requests for caching + [plugins](/configuration/resolve#resolve-plugins): [ + // ... + ] + // additional plugins applied to the resolver + </details> + }, + [performance](/configuration/performance): { + <details><summary>[hints](/configuration/performance#performance-hints): "warning", // enum </summary> + [hints](/configuration/performance#performance-hints): "error", // emit errors for perf hints + [hints](/configuration/performance#performance-hints): false, // turn off perf hints + </details> + [maxAssetSize](/configuration/performance#performance-maxassetsize): 200000, // int (in bytes), + [maxEntrypointSize](/configuration/performance#performance-maxentrypointsize): 400000, // int (in bytes) + [assetFilter](/configuration/performance#performance-assetfilter): function(assetFilename) { + // Function predicate that provides asset filenames + return assetFilename.endsWith('.css') || assetFilename.endsWith('.js'); + } + }, + <details><summary>[devtool](/configuration/devtool): "source-map", // enum </summary> + [devtool](/configuration/devtool): "inline-source-map", // inlines SourceMap into original file + [devtool](/configuration/devtool): "eval-source-map", // inlines SourceMap per module + [devtool](/configuration/devtool): "hidden-source-map", // SourceMap without reference in original file + [devtool](/configuration/devtool): "cheap-source-map", // cheap-variant of SourceMap without module mappings + [devtool](/configuration/devtool): "cheap-module-source-map", // cheap-variant of SourceMap with module mappings + [devtool](/configuration/devtool): "eval", // no SourceMap, but named modules. Fastest at the expense of detail. + </details> + // enhance debugging by adding meta info for the browser devtools + // source-map most detailed at the expense of build speed. + [context](/configuration/entry-context#context): __dirname, // string (absolute path!) + // the home directory for webpack + // the [entry](/configuration/entry-context) and [module.rules.loader](/configuration/module#rule-loader) option + // is resolved relative to this directory + <details><summary>[target](/configuration/target): "web", // enum</summary> + [target](/configuration/target): "webworker", // WebWorker + [target](/configuration/target): "node", // Node.js via require + [target](/configuration/target): "async-node", // Node.js via fs and vm + [target](/configuration/target): "node-webkit", // nw.js + [target](/configuration/target): "electron-main", // electron, main process + [target](/configuration/target): "electron-renderer", // electron, renderer process + [target](/configuration/target): (compiler) => { /* ... */ }, // custom + </details> + // the environment in which the bundle should run + // changes chunk loading behavior and available modules + <details><summary>[externals](/configuration/externals): ["react", /^@angular\//],</summary> + [externals](/configuration/externals): "react", // string (exact match) + [externals](/configuration/externals): /^[a-z\-]+($|\/)/, // Regex + [externals](/configuration/externals): { // object + angular: "this angular", // this["angular"] + react: { // UMD + commonjs: "react", + commonjs2: "react", + amd: "react", + root: "React" + } + }, + [externals](/configuration/externals): (request) => { /* ... */ return "commonjs " + request } + </details> + // Don't follow/bundle these modules, but request them at runtime from the environment + [serve](https://github.com/webpack-contrib/webpack-serve#options): { //object + port: 1337, + content: './dist', + // ... + }, + // lets you provide options for webpack-serve + <details><summary>[stats](/configuration/stats): "errors-only",</summary> + [stats](/configuration/stats): { //object + assets: true, + colors: true, + errors: true, + errorDetails: true, + hash: true, + // ... + }, + </details> + // lets you precisely control what bundle information gets displayed + [devServer](/configuration/dev-server): { + proxy: { // proxy URLs to backend development server + '/api': 'http://localhost:3000' + }, + contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location + compress: true, // enable gzip compression + historyApiFallback: true, // true for index.html upon 404, object for multiple paths + hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin + https: false, // true for self-signed, object for cert authority + noInfo: true, // only errors & warns on hot reload + // ... + }, + [plugins](plugins): [ + // ... + ], + // list of additional plugins + <details><summary>/* Advanced configuration (click to show) */</summary> + [resolveLoader](/configuration/resolve#resolveloader): { /* same as resolve */ } + // separate resolve options for loaders + [parallelism](other-options#parallelism): 1, // number + // limit the number of parallel processed modules + [profile](other-options#profile): true, // boolean + // capture timing information + [bail](other-options#bail): true, //boolean + // fail out on the first error instead of tolerating it. + [cache](other-options#cache): false, // boolean + // disable/enable caching + [watch](watch#watch): true, // boolean + // enables watching + [watchOptions](watch#watchoptions): { + [aggregateTimeout](watch#watchoptions-aggregatetimeout): 1000, // in ms + // aggregates multiple changes to a single rebuild + [poll](watch#watchoptions-poll): true, + [poll](watch#watchoptions-poll): 500, // interval in ms + // enables polling mode for watching + // must be used on filesystems that doesn't notify on change + // i. e. nfs shares + }, + [node](node): { + // Polyfills and mocks to run Node.js- + // environment code in non-Node environments. + [console](node#node-console): false, // boolean | "mock" + [global](node#node-global): true, // boolean | "mock" + [process](node#node-process): true, // boolean + [__filename](node#node-__filename): "mock", // boolean | "mock" + [__dirname](node#node-__dirname): "mock", // boolean | "mock" + [Buffer](node#node-buffer): true, // boolean | "mock" + [setImmediate](node#node-setimmediate): true // boolean | "mock" | "empty" + }, + [recordsPath](other-options#recordspath): path.resolve(__dirname, "build/records.json"), + [recordsInputPath](other-options#recordsinputpath): path.resolve(__dirname, "build/records.json"), + [recordsOutputPath](other-options#recordsoutputpath): path.resolve(__dirname, "build/records.json"), + // TODO + </details> +} +``` + +## Use custom configuration file + +If for some reason you want to use custom configuration file depending on certain situations you can change this via command line by using the `--config` flag. + +__package.json__ + +```json +"scripts": { + "build": "webpack --config prod.config.js" +} +``` + +## Configuration file generators + +Want to rapidly generate webpack configuration file for your project requirements with few clicks away? + +[Generate Custom Webpack Configuration](https://generatewebpackconfig.netlify.com/) is an interactive portal you can play around by selecting custom webpack configuration options tailored for your frontend project. It automatically generates a minimal webpack configuration based on your selection of loaders/plugins, etc. + +[Visual tool for creating webpack configs](https://webpack.jakoblind.no/) is an online configuration tool for creating webpack configuration file where you can select any combination of features you need. It also generates a full example project based on your webpack configs. + + +# Configuration Languages + +webpack accepts configuration files written in multiple programming and data languages. The list of supported file extensions can be found at the [node-interpret](https://github.com/js-cli/js-interpret) package. Using [node-interpret](https://github.com/js-cli/js-interpret), webpack can handle many different types of configuration files. + + +## TypeScript + +To write the webpack configuration in [TypeScript](http://www.typescriptlang.org/), you would first install the necessary dependencies, i.e., TypeScript and the relevant type definitions from the [DefinitelyTyped](https://definitelytyped.org/) project: + +``` bash +npm install --save-dev typescript ts-node @types/node @types/webpack +# and, if using webpack-dev-server +npm install --save-dev @types/webpack-dev-server +``` + +and then proceed to write your configuration: + +__webpack.config.ts__ + +```typescript +import path from 'path'; +import webpack from 'webpack'; + +const config: webpack.Configuration = { + mode: 'production', + entry: './foo.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'foo.bundle.js' + } +}; + +export default config; +``` + +Above sample assumes version >= 2.7 or newer of TypeScript is used with the new `esModuleInterop` and `allowSyntheticDefaultImports` compiler options in your `tsconfig.json` file. + +Note that you'll also need to check your `tsconfig.json` file. If the module in `compilerOptions` in `tsconfig.json` is `commonjs`, the setting is complete, else webpack will fail with an error. This occurs because `ts-node` does not support any module syntax other than `commonjs`. + +There are two solutions to this issue: + +- Modify `tsconfig.json`. +- Install `tsconfig-paths`. + +The __first option__ is to open your `tsconfig.json` file and look for `compilerOptions`. Set `target` to `"ES5"` and `module` to `"CommonJS"` (or completely remove the `module` option). + +The __second option__ is to install the `tsconfig-paths` package: + +``` bash +npm install --save-dev tsconfig-paths +``` + +And create a separate TypeScript configuration specifically for your webpack configs: + +__tsconfig-for-webpack-config.json__ + +``` json +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "esModuleInterop": true + } +} +``` + +T> `ts-node` can resolve a `tsconfig.json` file using the environment variable provided by `tsconfig-path`. + +Then set the environment variable `process.env.TS_NODE_PROJECT` provided by `tsconfig-path` like so: + +__package.json__ + +```json +{ + "scripts": { + "build": "TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack" + } +} +``` + + +## CoffeeScript + +Similarly, to use [CoffeeScript](http://coffeescript.org/), you would first install the necessary dependencies: + +``` bash +npm install --save-dev coffee-script +``` + +and then proceed to write your configuration: + +__webpack.config.coffee__ + +<!-- eslint-skip --> + +```js +HtmlWebpackPlugin = require('html-webpack-plugin') +webpack = require('webpack') +path = require('path') + +config = + mode: 'production' + entry: './path/to/my/entry/file.js' + output: + path: path.resolve(__dirname, 'dist') + filename: 'my-first-webpack.bundle.js' + module: rules: [ { + test: /\.(js|jsx)$/ + use: 'babel-loader' + } ] + plugins: [ + new HtmlWebpackPlugin(template: './src/index.html') + ] + +module.exports = config +``` + + +## Babel and JSX + +In the example below JSX (React JavaScript Markup) and Babel are used to create a JSON Configuration that webpack can understand. + +> Courtesy of [Jason Miller](https://twitter.com/_developit/status/769583291666169862) + +First install the necessary dependencies: + +``` bash +npm install --save-dev babel-register jsxobj babel-preset-es2015 +``` + +__.babelrc__ + +``` json +{ + "presets": [ "es2015" ] +} +``` + +__webpack.config.babel.js__ + +``` js +import jsxobj from 'jsxobj'; + +// example of an imported plugin +const CustomPlugin = config => ({ + ...config, + name: 'custom-plugin' +}); + +export default ( + <webpack target="web" watch mode="production"> + <entry path="src/index.js" /> + <resolve> + <alias {...{ + react: 'preact-compat', + 'react-dom': 'preact-compat' + }} /> + </resolve> + <plugins> + <CustomPlugin foo="bar" /> + </plugins> + </webpack> +); +``` + +W> If you are using Babel elsewhere and have `modules` set to `false`, you will have to either maintain two separate `.babelrc` files or use `const jsxobj = require('jsxobj');` and `module.exports` instead of the new `import` and `export` syntax. This is because while Node does support many new ES6 features, they don't yet support ES6 module syntax. + + +# Configuration Types + +Besides exporting a single config object, there are a few more ways that cover other needs as well. + + +## Exporting a Function + +Eventually you will find the need to disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production). You have (at least) two options: + +One option is to export a function from your webpack config instead of exporting an object. The function will be invoked with two arguments: + +- An environment as the first parameter. See the [environment options CLI documentation](/api/cli#environment-options) for syntax examples. +- An options map (`argv`) as the second parameter. This describes the options passed to webpack, with keys such as [`output-filename`](/api/cli/#output-options) and [`optimize-minimize`](/api/cli/#optimize-options). + +```diff +-module.exports = { ++module.exports = function(env, argv) { ++ return { ++ mode: env.production ? 'production' : 'development', ++ devtool: env.production ? 'source-maps' : 'eval', + plugins: [ + new TerserPlugin({ + terserOptions: { ++ compress: argv['optimize-minimize'] // only if -p or --optimize-minimize were passed + } + }) + ] ++ }; +}; +``` + + +## Exporting a Promise + +webpack will run the function exported by the configuration file and wait for a Promise to be returned. Handy when you need to asynchronously load configuration variables. + +```js +module.exports = () => { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve({ + entry: './app.js', + /* ... */ + }); + }, 5000); + }); +}; +``` + + +## Exporting multiple configurations + +Instead of exporting a single configuration object/function, you may export multiple configurations (multiple functions are supported since webpack 3.1.0). When running webpack, all configurations are built. For instance, this is useful for [bundling a library](/guides/author-libraries) for multiple [targets](/configuration/output#output-librarytarget) such as AMD and CommonJS: + +```js +module.exports = [{ + output: { + filename: './dist-amd.js', + libraryTarget: 'amd' + }, + name: 'amd', + entry: './app.js', + mode: 'production', +}, { + output: { + filename: './dist-commonjs.js', + libraryTarget: 'commonjs' + }, + name: 'commonjs', + entry: './app.js', + mode: 'production', +}]; +``` + +T> If you pass a name to [`--config-name`](/api/cli/#config-options) flag, webpack will only build that specific configuration. + + +# Entry and Context + +The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. + + +## `context` + +`string` + +The base directory, an __absolute path__, for resolving entry points and loaders from configuration. + +``` js +module.exports = { + //... + context: path.resolve(__dirname, 'app') +}; +``` + +By default the current directory is used, but it's recommended to pass a value in your configuration. This makes your configuration independent from CWD (current working directory). + +--- + + +## `entry` + +`string | [string] | object { <key>: string | [string] } | (function: () => string | [string] | object { <key>: string | [string] })` + +The point or points to enter the application. At this point the application starts executing. If an array is passed all items will be executed. + +A dynamically loaded module is __not__ an entry point. + +Simple rule: one entry point per HTML page. SPA: one entry point, MPA: multiple entry points. + +```js +module.exports = { + //... + entry: { + home: './home.js', + about: './about.js', + contact: './contact.js' + } +}; +``` + + +### Naming + +If a string or array of strings is passed, the chunk is named `main`. If an object is passed, each key is the name of a chunk, and the value describes the entry point for the chunk. + + +### Dynamic entry + +If a function is passed then it will be invoked on every [make](/api/compiler-hooks/#make) event. + +> Note that the make event triggers when webpack starts and for every invalidation when [watching for file changes](/configuration/watch/). + +```js +module.exports = { + //... + entry: () => './demo' +}; +``` + +or + +```js +module.exports = { + //... + entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])) +}; +``` + +For example: you can use dynamic entries to get the actual entries from an external source (remote server, file system content or database): + +__webpack.config.js__ + +``` js +module.exports = { + entry() { + return fetchPathsFromSomeExternalSource(); // returns a promise that will be resolved with something like ['src/main-layout.js', 'src/admin-layout.js'] + } +}; +``` + +When combining with the [`output.library`](/configuration/output#output-library) option: If an array is passed only the last item is exported. + + +# Output + +The top-level `output` key contains set of options instructing webpack on how and where it should output your bundles, assets and anything else you bundle or load with webpack. + + +## `output.auxiliaryComment` + +`string` `object` + +When used in tandem with [`output.library`](#output-library) and [`output.libraryTarget`](#output-librarytarget), this option allows users to insert comments within the export wrapper. To insert the same comment for each `libraryTarget` type, set `auxiliaryComment` to a string: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + library: 'someLibName', + libraryTarget: 'umd', + filename: 'someLibName.js', + auxiliaryComment: 'Test Comment' + } +}; +``` + +which will yield the following: + +__webpack.config.js__ + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + // Test Comment + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require('lodash')); + // Test Comment + else if(typeof define === 'function' && define.amd) + define(['lodash'], factory); + // Test Comment + else if(typeof exports === 'object') + exports['someLibName'] = factory(require('lodash')); + // Test Comment + else + root['someLibName'] = factory(root['_']); +})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { + // ... +}); +``` + +For fine-grained control over each `libraryTarget` comment, pass an object: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + //... + auxiliaryComment: { + root: 'Root Comment', + commonjs: 'CommonJS Comment', + commonjs2: 'CommonJS2 Comment', + amd: 'AMD Comment' + } + } +}; +``` + + +## `output.chunkFilename` + +`string` + +This option determines the name of non-entry chunk files. See [`output.filename`](#output-filename) option for details on the possible values. + +Note that these filenames need to be generated at runtime to send the requests for chunks. Because of this, placeholders like `[name]` and `[chunkhash]` need to add a mapping from chunk id to placeholder value to the output bundle with the webpack runtime. This increases the size and may invalidate the bundle when placeholder value for any chunk changes. + +By default `[id].js` is used or a value inferred from [`output.filename`](#output-filename) (`[name]` is replaced with `[id]` or `[id].` is prepended). + + +## `output.chunkLoadTimeout` + +`integer` + +Number of milliseconds before chunk request expires, defaults to 120 000. This option is supported since webpack 2.6.0. + + +## `output.crossOriginLoading` + +`boolean` `string` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks, by adding script tags. + +Enable [cross-origin](https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-crossorigin) loading of chunks. The following values are accepted... + +`crossOriginLoading: false` - Disable cross-origin loading (default) + +`crossOriginLoading: 'anonymous'` - Enable cross-origin loading __without credentials__ + +`crossOriginLoading: 'use-credentials'` - Enable cross-origin loading __with credentials__ + + +## `output.jsonpScriptType` + +`string` + +Allows customization of the `script` type webpack injects `script` tags into the DOM to download async chunks. The following options are available: + +- `'text/javascript'` (default) +- `'module'`: Use with ES6 ready code. + + +## `output.devtoolFallbackModuleFilenameTemplate` + +`string | function(info)` + +A fallback used when the template string or function above yields duplicates. + +See [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). + + +## `output.devtoolLineToLine` + +`boolean | object` + +> Avoid using this option as it is __deprecated__ and will soon be removed. + +Enables line to line mapping for all or some modules. This produces a simple source map where each line of the generated source is mapped to the same line of the original source. This is a performance optimization and should only be used if all input lines match generated lines. + +Pass a boolean to enable or disable this feature for all modules (defaults to `false`). An object with `test`, `include`, `exclude` is also allowed. For example, to enable this feature for all javascript files within a certain directory: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + devtoolLineToLine: { test: /\.js$/, include: 'src/utilities' } + } +}; +``` + + +## `output.devtoolModuleFilenameTemplate` + +`string | function(info)` + +This option is only used when [`devtool`](/configuration/devtool) uses an options which requires module names. + +Customize the names used in each source map's `sources` array. This can be done by passing a template string or function. For example, when using `devtool: 'eval'`, this is the default: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + devtoolModuleFilenameTemplate: 'webpack://[namespace]/[resource-path]?[loaders]' + } +}; +``` + +The following substitutions are available in template strings (via webpack's internal [`ModuleFilenameHelpers`](https://github.com/webpack/webpack/blob/master/lib/ModuleFilenameHelpers.js)): + +| Template | Description | +| ------------------------ | ----------- | +| [absolute-resource-path] | The absolute filename | +| [all-loaders] | Automatic and explicit loaders and params up to the name of the first loader | +| [hash] | The hash of the module identifier | +| [id] | The module identifier | +| [loaders] | Explicit loaders and params up to the name of the first loader | +| [resource] | The path used to resolve the file and any query params used on the first loader | +| [resource-path] | The path used to resolve the file without any query params | +| [namespace] | The modules namespace. This is usually the library name when building as a library, empty otherwise | + +When using a function, the same options are available camel-cased via the `info` parameter: + +```javascript +module.exports = { + //... + output: { + devtoolModuleFilenameTemplate: info => { + return `webpack:///${info.resourcePath}?${info.loaders}`; + } + } +}; +``` + +If multiple modules would result in the same name, [`output.devtoolFallbackModuleFilenameTemplate`](#output-devtoolfallbackmodulefilenametemplate) is used instead for these modules. + + +## `output.devtoolNamespace` + +`string` + +This option determines the modules namespace used with the [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). When not specified, it will default to the value of: [`output.library`](#output-library). It's used to prevent source file path collisions in source maps when loading multiple libraries built with webpack. + +For example, if you have 2 libraries, with namespaces `library1` and `library2`, which both have a file `./src/index.js` (with potentially different contents), they will expose these files as `webpack://library1/./src/index.js` and `webpack://library2/./src/index.js`. + + +## `output.filename` + +`string` `function` + +This option determines the name of each output bundle. The bundle is written to the directory specified by the [`output.path`](#output-path) option. + +For a single [`entry`](/configuration/entry-context#entry) point, this can be a static name. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: 'bundle.js' + } +}; +``` + +However, when creating multiple bundles via more than one entry point, code splitting, or various plugins, you should use one of the following substitutions to give each bundle a unique name... + +Using entry name: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[name].bundle.js' + } +}; +``` + +Using internal chunk id: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[id].bundle.js' + } +}; +``` + +Using the unique hash generated for every build: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[name].[hash].bundle.js' + } +}; +``` + +Using hashes based on each chunks' content: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[chunkhash].bundle.js' + } +}; +``` + +Using hashes generated for extracted content: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: '[contenthash].bundle.css' + } +}; +``` + +Using function to return the filename: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: (chunkData) => { + return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js'; + }, + } +}; +``` + +Make sure to read the [Caching guide](/guides/caching) for details. There are more steps involved than just setting this option. + +Note this option is called filename but you are still allowed to use something like `'js/[name]/bundle.js'` to create a folder structure. + +Note this option does not affect output files for on-demand-loaded chunks. For these files the [`output.chunkFilename`](#output-chunkfilename) option is used. Files created by loaders also aren't affected. In this case you would have to try the specific loader's available options. + +The following substitutions are available in template strings (via webpack's internal [`TemplatedPathPlugin`](https://github.com/webpack/webpack/blob/master/lib/TemplatedPathPlugin.js)): + +| Template | Description | +| ----------- | ----------------------------------------------------------------------------------- | +| [hash] | The hash of the module identifier | +| [chunkhash] | The hash of the chunk content | +| [name] | The module name | +| [id] | The module identifier | +| [query] | The module query, i.e., the string following `?` in the filename | +| [function] | The function, which can return filename [string] | + +The lengths of `[hash]` and `[chunkhash]` can be specified using `[hash:16]` (defaults to 20). Alternatively, specify [`output.hashDigestLength`](#output-hashdigestlength) to configure the length globally. + +If using a function for this option, the function will be passed an object containing the substitutions in the table above. + +T> When using the [`ExtractTextWebpackPlugin`](/plugins/extract-text-webpack-plugin), use `[contenthash]` to obtain a hash of the extracted file (neither `[hash]` nor `[chunkhash]` work). + + +## `output.hashDigest` + +The encoding to use when generating the hash, defaults to `'hex'`. All encodings from Node.JS' [`hash.digest`](https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding) are supported. Using `'base64'` for filenames might be problematic since it has the character `/` in its alphabet. Likewise `'latin1'` could contain any character. + + +## `output.hashDigestLength` + +The prefix length of the hash digest to use, defaults to `20`. + + +## `output.hashFunction` + +`string|function` + +The hashing algorithm to use, defaults to `'md4'`. All functions from Node.JS' [`crypto.createHash`](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options) are supported. Since `4.0.0-alpha2`, the `hashFunction` can now be a constructor to a custom hash function. You can provide a non-crypto hash function for performance reasons. + +```javascript +module.exports = { + //... + output: { + hashFunction: require('metrohash').MetroHash64 + } +}; +``` + +Make sure that the hashing function will have `update` and `digest` methods available. + +## `output.hashSalt` + +An optional salt to update the hash via Node.JS' [`hash.update`](https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding). + + +## `output.hotUpdateChunkFilename` + +`string` `function` + +Customize the filenames of hot update chunks. See [`output.filename`](#output-filename) option for details on the possible values. + +The only placeholders allowed here are `[id]` and `[hash]`, the default being: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + hotUpdateChunkFilename: '[id].[hash].hot-update.js' + } +}; +``` + +Here is no need to change it. + + +## `output.hotUpdateFunction` + +`function` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading hot updates. + +A JSONP function used to asynchronously load hot-update chunks. + +For details see [`output.jsonpFunction`](#output-jsonpfunction). + + +## `output.hotUpdateMainFilename` + +`string` `function` + +Customize the main hot update filename. See [`output.filename`](#output-filename) option for details on the possible values. + +`[hash]` is the only available placeholder, the default being: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + hotUpdateMainFilename: '[hash].hot-update.json' + } +}; +``` + +Here is no need to change it. + + +## `output.jsonpFunction` + +`string` + +Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks. + +A JSONP function name used to asynchronously load chunks or join multiple initial chunks (SplitChunksPlugin, AggressiveSplittingPlugin). + +This needs to be changed if multiple webpack runtimes (from different compilation) are used on the same webpage. + +If using the [`output.library`](#output-library) option, the library name is automatically appended. + + +## `output.library` + +`string` or `object` (since webpack 3.1.0; for `libraryTarget: 'umd'`) + +How the value of the `output.library` is used depends on the value of the [`output.libraryTarget`](#output-librarytarget) option; please refer to that section for the complete details. Note that the default option for `output.libraryTarget` is `var`, so if the following configuration option is used: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary' + } +}; +``` + +The variable `MyLibrary` will be bound with the return value of your entry file, if the resulting output is included as a script tag in an HTML page. + +W> Note that if an `array` is provided as an `entry` point, only the last module in the array will be exposed. If an `object` is provided, it can be exposed using an `array` syntax (see [this example](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) for details). + +T> Read the [authoring libraries guide](/guides/author-libraries) guide for more information on `output.library` as well as `output.libraryTarget`. + + +## `output.libraryExport` + +`string | string[]` + +Configure which module or modules will be exposed via the `libraryTarget`. It is `undefined` by default, same behaviour will be applied if you set `libraryTarget` to an empty string e.g. `''` it will export the whole (namespace) object. The examples below demonstrate the effect of this config when using `libraryTarget: 'var'`. + +The following configurations are supported: + +`libraryExport: 'default'` - The __default export of your entry point__ will be assigned to the library target: + +```javascript +// if your entry has a default export of `MyDefaultModule` +var MyDefaultModule = _entry_return_.default; +``` + +`libraryExport: 'MyModule'` - The __specified module__ will be assigned to the library target: + +```javascript +var MyModule = _entry_return_.MyModule; +``` + +`libraryExport: ['MyModule', 'MySubModule']` - The array is interpreted as a __path to a module__ to be assigned to the library target: + +```javascript +var MySubModule = _entry_return_.MyModule.MySubModule; +``` + +With the `libraryExport` configurations specified above, the resulting libraries could be utilized as such: + +```javascript +MyDefaultModule.doSomething(); +MyModule.doSomething(); +MySubModule.doSomething(); +``` + + +## `output.libraryTarget` + +`string: 'var'` + +Configure how the library will be exposed. Any one of the following options can be used. Please note that this option works in conjunction with the value assigned to [`output.library`](#output-library). For the following examples, it is assumed that this value is configured as `MyLibrary`. + +T> Note that `_entry_return_` in the example code below is the value returned by the entry point. In the bundle itself, it is the output of the function that is generated by webpack from the entry point. + +### Expose a Variable + +These options assign the return value of the entry point (e.g. whatever the entry point exported) to the name provided by `output.library` at whatever scope the bundle was included at. + +`libraryTarget: 'var'` - (default) When your library is loaded, the __return value of your entry point__ will be assigned to a variable: + +```javascript +var MyLibrary = _entry_return_; + +// In a separate script... +MyLibrary.doSomething(); +``` + +W> When using this option, an empty `output.library` will result in no assignment. + + +`libraryTarget: 'assign'` - This will generate an implied global which has the potential to reassign an existing value (use with caution). + +```javascript +MyLibrary = _entry_return_; +``` + +Be aware that if `MyLibrary` isn't defined earlier your library will be set in global scope. + +W> When using this option, an empty `output.library` will result in a broken output bundle. + + +### Expose Via Object Assignment + +These options assign the return value of the entry point (e.g. whatever the entry point exported) to a specific object under the name defined by `output.library`. + +If `output.library` is not assigned a non-empty string, the default behavior is that all properties returned by the entry point will be assigned to the object as defined for the particular `output.libraryTarget`, via the following code fragment: + +```javascript +(function(e, a) { for(var i in a) { e[i] = a[i]; } }(output.libraryTarget, _entry_return_)); +``` + +W> Note that not setting a `output.library` will cause all properties returned by the entry point to be assigned to the given object; there are no checks against existing property names. + +`libraryTarget: "this"` - The __return value of your entry point__ will be assigned to this under the property named by `output.library`. The meaning of `this` is up to you: + +```javascript +this['MyLibrary'] = _entry_return_; + +// In a separate script... +this.MyLibrary.doSomething(); +MyLibrary.doSomething(); // if this is window +``` + +`libraryTarget: 'window'` - The __return value of your entry point__ will be assigned to the `window` object using the `output.library` value. + +```javascript +window['MyLibrary'] = _entry_return_; + +window.MyLibrary.doSomething(); +``` + + +`libraryTarget: 'global'` - The __return value of your entry point__ will be assigned to the `global` object using the `output.library` value. + +```javascript +global['MyLibrary'] = _entry_return_; + +global.MyLibrary.doSomething(); +``` + + +`libraryTarget: 'commonjs'` - The __return value of your entry point__ will be assigned to the `exports` object using the `output.library` value. As the name implies, this is used in CommonJS environments. + +```javascript +exports['MyLibrary'] = _entry_return_; + +require('MyLibrary').doSomething(); +``` + +### Module Definition Systems + +These options will result in a bundle that comes with a more complete header to ensure compatibility with various module systems. The `output.library` option will take on a different meaning under the following `output.libraryTarget` options. + + +`libraryTarget: 'commonjs2'` - The __return value of your entry point__ will be assigned to the `module.exports`. As the name implies, this is used in CommonJS environments: + +```javascript +module.exports = _entry_return_; + +require('MyLibrary').doSomething(); +``` + +Note that `output.library` is omitted, thus it is not required for this particular `output.libraryTarget`. + +T> Wondering the difference between CommonJS and CommonJS2 is? While they are similar, there are some subtle differences between them that are not usually relevant in the context of webpack. (For further details, please [read this issue](https://github.com/webpack/webpack/issues/1114).) + + +`libraryTarget: 'amd'` - This will expose your library as an AMD module. + +AMD modules require that the entry chunk (e.g. the first script loaded by the `<script>` tag) be defined with specific properties, such as `define` and `require` which is typically provided by RequireJS or any compatible loaders (such as almond). Otherwise, loading the resulting AMD bundle directly will result in an error like `define is not defined`. + +So, with the following configuration... + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary', + libraryTarget: 'amd' + } +}; +``` + +The generated output will be defined with the name "MyLibrary", i.e. + +```javascript +define('MyLibrary', [], function() { + return _entry_return_; +}); +``` + +The bundle can be included as part of a script tag, and the bundle can be invoked like so: + +```javascript +require(['MyLibrary'], function(MyLibrary) { + // Do something with the library... +}); +``` + +If `output.library` is undefined, the following is generated instead. + +```javascript +define([], function() { + return _entry_return_; +}); +``` + +This bundle will not work as expected, or not work at all (in the case of the almond loader) if loaded directly with a `<script>` tag. It will only work through a RequireJS compatible asynchronous module loader through the actual path to that file, so in this case, the `output.path` and `output.filename` may become important for this particular setup if these are exposed directly on the server. + + +`libraryTarget: 'amd-require'` - This packages your output with an immediately-executed AMD `require(dependencies, factory)` wrapper. + +The `'amd-require'` target allows for the use of AMD dependencies without needing a separate later invocation. As with the `'amd'` target, this depends on the appropriate [`require` function](https://github.com/amdjs/amdjs-api/blob/master/require.md) being available in the environment in which the webpack output is loaded. + +With this target, the library name is ignored. + + +`libraryTarget: 'umd'` - This exposes your library under all the module definitions, allowing it to work with CommonJS, AMD and as global variable. Take a look at the [UMD Repository](https://github.com/umdjs/umd) to learn more. + +In this case, you need the `library` property to name your module: + +```javascript +module.exports = { + //... + output: { + library: 'MyLibrary', + libraryTarget: 'umd' + } +}; +``` + +And finally the output is: + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports['MyLibrary'] = factory(); + else + root['MyLibrary'] = factory(); +})(typeof self !== 'undefined' ? self : this, function() { + return _entry_return_; +}); +``` + +Note that omitting `library` will result in the assignment of all properties returned by the entry point be assigned directly to the root object, as documented under the [object assignment section](#expose-via-object-assignment). Example: + +```javascript +module.exports = { + //... + output: { + libraryTarget: 'umd' + } +}; +``` + +The output will be: + +```javascript +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else { + var a = factory(); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(typeof self !== 'undefined' ? self : this, function() { + return _entry_return_; +}); +``` + +Since webpack 3.1.0, you may specify an object for `library` for differing names per targets: + +```javascript +module.exports = { + //... + output: { + library: { + root: 'MyLibrary', + amd: 'my-library', + commonjs: 'my-common-library' + }, + libraryTarget: 'umd' + } +}; +``` + +Module proof library. + + +### Other Targets + +`libraryTarget: 'jsonp'` - This will wrap the return value of your entry point into a jsonp wrapper. + +``` javascript +MyLibrary(_entry_return_); +``` + +The dependencies for your library will be defined by the [`externals`](/configuration/externals/) config. + + +## `output.path` + +`string` + +The output directory as an __absolute__ path. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + path: path.resolve(__dirname, 'dist/assets') + } +}; +``` + +Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. + + +## `output.pathinfo` + +`boolean` + +Tells webpack to include comments in bundles with information about the contained modules. This option defaults to `true` in `development` and `false` in `production` [mode](/concepts/mode/) respectively. + +W> While the data this comments can provide is very useful during development when reading the generated code, it __should not__ be used in production. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + pathinfo: true + } +}; +``` + +Note it also adds some info about tree shaking to the generated bundle. + + +## `output.publicPath` + +`string: ''` `function` + +This is an important option when using on-demand-loading or loading external resources like images, files, etc. If an incorrect value is specified you'll receive 404 errors while loading these resources. + +This option specifies the __public URL__ of the output directory when referenced in a browser. A relative URL is resolved relative to the HTML page (or `<base>` tag). Server-relative URLs, protocol-relative URLs or absolute URLs are also possible and sometimes required, i. e. when hosting assets on a CDN. + +The value of the option is prefixed to every URL created by the runtime or loaders. Because of this __the value of this option ends with `/`__ in most cases. + +Simple rule: The URL of your [`output.path`](#output-path) from the view of the HTML page. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + path: path.resolve(__dirname, 'public/assets'), + publicPath: 'https://cdn.example.com/assets/' + } +}; +``` + +For this configuration: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + publicPath: '/assets/', + chunkFilename: '[id].chunk.js' + } +}; +``` + +A request to a chunk will look like `/assets/4.chunk.js`. + +A loader outputting HTML might emit something like this: + +```html +<link href="/assets/spinner.gif" /> +``` + +or when loading an image in CSS: + +```css +background-image: url(/assets/spinner.gif); +``` + +The webpack-dev-server also takes a hint from `publicPath`, using it to determine where to serve the output files from. + +Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. + +Examples: + +```javascript +module.exports = { + //... + output: { + // One of the below + publicPath: 'https://cdn.example.com/assets/', // CDN (always HTTPS) + publicPath: '//cdn.example.com/assets/', // CDN (same protocol) + publicPath: '/assets/', // server-relative + publicPath: 'assets/', // relative to HTML page + publicPath: '../assets/', // relative to HTML page + publicPath: '', // relative to HTML page (same directory) + } +}; +``` + +In cases where the `publicPath` of output files can't be known at compile time, it can be left blank and set dynamically at runtime in the entry file using the [free variable](https://stackoverflow.com/questions/12934929/what-are-free-variables) `__webpack_public_path__`. + +```javascript +__webpack_public_path__ = myRuntimePublicPath; + +// rest of your application entry +``` + +See [this discussion](https://github.com/webpack/webpack/issues/2776#issuecomment-233208623) for more information on `__webpack_public_path__`. + + +## `output.sourceMapFilename` + +`string` + +This option is only used when [`devtool`](/configuration/devtool) uses a SourceMap option which writes an output file. + +Configure how source maps are named. By default `'[file].map'` is used. + +The `[name]`, `[id]`, `[hash]` and `[chunkhash]` substitutions from [#output-filename](#output-filename) can be used. In addition to those, you can use substitutions listed below. The `[file]` placeholder is replaced with the filename of the original file. We recommend __only using the `[file]` placeholder__, as the other placeholders won't work when generating SourceMaps for non-chunk files. + +| Template | Description | +| -------------------------- | ----------------------------------------------------------------------------------- | +| [file] | The module filename | +| [filebase] | The module [basename](https://nodejs.org/api/path.html#path_path_basename_path_ext) | + + +## `output.sourcePrefix` + +`string` + +Change the prefix for each line in the output bundles. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + sourcePrefix: '\t' + } +}; +``` + +Note by default an empty string is used. Using some kind of indentation makes bundles look more pretty, but will cause issues with multi-line strings. + +There is no need to change it. + + +## `output.strictModuleExceptionHandling` + +`boolean` + +Tell webpack to remove a module from the module instance cache (`require.cache`) if it throws an exception when it is `require`d. + +It defaults to `false` for performance reasons. + +When set to `false`, the module is not removed from cache, which results in the exception getting thrown only on the first `require` call (making it incompatible with node.js). + +For instance, consider `module.js`: + +```javascript +throw new Error('error'); +``` + +With `strictModuleExceptionHandling` set to `false`, only the first `require` throws an exception: + +```javascript +// with strictModuleExceptionHandling = false +require('module'); // <- throws +require('module'); // <- doesn't throw +``` + +Instead, with `strictModuleExceptionHandling` set to `true`, all `require`s of this module throw an exception: + +```javascript +// with strictModuleExceptionHandling = true +require('module'); // <- throws +require('module'); // <- also throws +``` + + +## `output.umdNamedDefine` + +`boolean` + +When using `libraryTarget: "umd"`, setting: + +```javascript +module.exports = { + //... + output: { + umdNamedDefine: true + } +}; +``` + +will name the AMD module of the UMD build. Otherwise an anonymous `define` is used. + + +# Module + +These options determine how the [different types of modules](/concepts/modules) within a project will be treated. + + +## `module.noParse` + +`RegExp | [RegExp] | function | string | [string]` + +Prevent webpack from parsing any files matching the given regular expression(s). Ignored files __should not__ have calls to `import`, `require`, `define` or any other importing mechanism. This can boost build performance when ignoring large libraries. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + noParse: /jquery|lodash/, + } +}; +``` + +```javascript +module.exports = { + //... + module: { + noParse: (content) => /jquery|lodash/.test(content) + } +}; +``` + + +## `module.rules` + +`[Rule]` + +An array of [Rules](#rule) which are matched to requests when modules are created. These rules can modify how the module is created. They can apply loaders to the module, or modify the parser. + + +## Rule + +`object` + +A Rule can be separated into three parts — Conditions, Results and nested Rules. + + +### Rule Conditions + +There are two input values for the conditions: + +1. The resource: An absolute path to the file requested. It's already resolved according to the [`resolve` rules](/configuration/resolve). + +2. The issuer: An absolute path to the file of the module which requested the resource. It's the location of the import. + +__Example:__ When we `import './style.css'` within `app.js`, the resource is `/path/to/style.css` and the issuer is `/path/to/app.js`. + +In a Rule the properties [`test`](#rule-test), [`include`](#rule-include), [`exclude`](#rule-exclude) and [`resource`](#rule-resource) are matched with the resource and the property [`issuer`](#rule-issuer) is matched with the issuer. + +When using multiple conditions, all conditions must match. + +W> Be careful! The resource is the _resolved_ path of the file, which means symlinked resources are the real path _not_ the symlink location. This is good to remember when using tools that symlink packages (like `npm link`), common conditions like `/node_modules/` may inadvertently miss symlinked files. Note that you can turn off symlink resolving (so that resources are resolved to the symlink path) via [`resolve.symlinks`](/configuration/resolve#resolve-symlinks). + + +### Rule results + +Rule results are used only when the Rule condition matches. + +There are two output values of a Rule: + +1. Applied loaders: An array of loaders applied to the resource. +2. Parser options: An options object which should be used to create the parser for this module. + +These properties affect the loaders: [`loader`](#rule-loader), [`options`](#rule-options-rule-query), [`use`](#rule-use). + +For compatibility also these properties: [`query`](#rule-options-rule-query), [`loaders`](#rule-loaders). + +The [`enforce`](#rule-enforce) property affects the loader category. Whether it's a normal, pre- or post- loader. + +The [`parser`](#rule-parser) property affects the parser options. + + +## Nested rules + +Nested rules can be specified under the properties [`rules`](#rule-rules) and [`oneOf`](#rule-oneof). + +These rules are evaluated when the Rule condition matches. + + +## `Rule.enforce` + +`string` + +Possible values: `'pre' | 'post'` + +Specifies the category of the loader. No value means normal loader. + +There is also an additional category "inlined loader" which are loaders applied inline of the import/require. + +There are two phases that all loaders enter one after the other: + +1. __Pitching__ phase: the pitch method on loaders is called in the order `post, inline, normal, pre`. See [Pitching Loader](/api/loaders/#pitching-loader) for details. +2. __Normal__ phase: the normal method on loaders is executed in the order `pre, normal, inline, post`. Transformation on the source code of a module happens in this phase. + +All normal loaders can be omitted (overridden) by prefixing `!` in the request. + +All normal and pre loaders can be omitted (overridden) by prefixing `-!` in the request. + +All normal, post and pre loaders can be omitted (overridden) by prefixing `!!` in the request. + +Inline loaders and `!` prefixes should not be used as they are non-standard. They may be use by loader generated code. + + +## `Rule.exclude` + +`Rule.exclude` is a shortcut to `Rule.resource.exclude`. If you supply a `Rule.exclude` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.exclude`](#condition) for details. + + +## `Rule.include` + +`Rule.include` is a shortcut to `Rule.resource.include`. If you supply a `Rule.include` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.include`](#condition) for details. + + +## `Rule.issuer` + +A [`Condition`](#condition) to match against the module that issued the request. In the following example, the `issuer` for the `a.js` request would be the path to the `index.js` file. + +__index.js__ + +```javascript +import A from './a.js'; +``` + +This option can be used to apply loaders to the dependencies of a specific module or set of modules. + + +## `Rule.loader` + +`Rule.loader` is a shortcut to `Rule.use: [ { loader } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.loader`](#useentry) for details. + + +## `Rule.loaders` + +W> This option is __deprecated__ in favor of `Rule.use`. + +`Rule.loaders` is an alias to `Rule.use`. See [`Rule.use`](#rule-use) for details. + + +## `Rule.oneOf` + +An array of [`Rules`](#rule) from which only the first matching Rule is used when the Rule matches. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + oneOf: [ + { + resourceQuery: /inline/, // foo.css?inline + use: 'url-loader' + }, + { + resourceQuery: /external/, // foo.css?external + use: 'file-loader' + } + ] + } + ] + } +}; +``` + +## `Rule.options` / `Rule.query` + +`Rule.options` and `Rule.query` are shortcuts to `Rule.use: [ { options } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.options`](#useentry) for details. + +W> `Rule.query` is deprecated in favor of `Rule.options` and `UseEntry.options`. + + +## `Rule.parser` + +An object with parser options. All applied parser options are merged. + +Parsers may inspect these options and disable or reconfigure themselves accordingly. Most of the default plugins interpret the values as follows: + +- Setting the option to `false` disables the parser. +- Setting the option to `true` or leaving it `undefined` enables the parser. + +However, parser plugins may accept more than just a boolean. For example, the internal `NodeStuffPlugin` can accept an object instead of `true` to add additional options for a particular Rule. + +__Examples__ (parser options by the default plugins): + +```js-with-links +module.exports = { + //... + module: { + rules: [ + { + //... + parser: { + amd: false, // disable AMD + commonjs: false, // disable CommonJS + system: false, // disable SystemJS + harmony: false, // disable ES2015 Harmony import/export + requireInclude: false, // disable require.include + requireEnsure: false, // disable require.ensure + requireContext: false, // disable require.context + browserify: false, // disable special handling of Browserify bundles + requireJs: false, // disable requirejs.* + node: false, // disable __dirname, __filename, module, require.extensions, require.main, etc. + node: {...} // reconfigure [node](/configuration/node) layer on module level + } + } + ] + } +} +``` + + +## `Rule.resource` + +A [`Condition`](#condition) matched with the resource. You can either supply a `Rule.resource` option or use the shortcut options `Rule.test`, `Rule.exclude`, and `Rule.include`. See details in [`Rule` conditions](#rule-conditions). + + +## `Rule.resourceQuery` + +A [`Condition`](#condition) matched with the resource query. This option is used to test against the query section of a request string (i.e. from the question mark onwards). If you were to `import Foo from './foo.css?inline'`, the following condition would match: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + resourceQuery: /inline/, + use: 'url-loader' + } + ] + } +}; +``` + + +## `Rule.rules` + +An array of [`Rules`](#rule) that is also used when the Rule matches. + + +## `Rule.sideEffects` + +`bool` + +Indicate what parts of the module contain side effects. See [Tree Shaking](/guides/tree-shaking/#mark-the-file-as-side-effect-free) for details. + + +## `Rule.test` + +`Rule.test` is a shortcut to `Rule.resource.test`. If you supply a `Rule.test` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.test`](#condition) for details. + + +## `Rule.type` + +`string` + +Possible values: `'javascript/auto' | 'javascript/dynamic' | 'javascript/esm' | 'json' | 'webassembly/experimental'` + +`Rule.type` sets the type for a matching module. This prevents defaultRules and their default importing behaviors from occurring. For example, if you want to load a `.json` file through a custom loader, you'd need to set the `type` to `javascript/auto` to bypass webpack's built-in json importing. (See [v4.0 changelog](https://github.com/webpack/webpack/releases/tag/v4.0.0) for more details) + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + //... + { + test: /\.json$/, + type: 'javascript/auto', + loader: 'custom-json-loader' + } + ] + } +}; +``` + + +## `Rule.use` + +A list of [UseEntries](#useentry) which are applied to modules. Each entry specifies a loader to be used. + +Passing a string (i.e. `use: [ 'style-loader' ]`) is a shortcut to the loader property (i.e. `use: [ { loader: 'style-loader '} ]`). + +Loaders can be chained by passing multiple loaders, which will be applied from right to left (last to first configured). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + //... + use: [ + 'style-loader', + { + loader: 'css-loader', + options: { + importLoaders: 1 + } + }, + { + loader: 'less-loader', + options: { + noIeCompat: true + } + } + ] + } + ] + } +}; +``` + +See [UseEntry](#useentry) for details. + + +## `Condition` + +Conditions can be one of these: + +- A string: To match the input must start with the provided string. I. e. an absolute directory path, or absolute path to the file. +- A RegExp: It's tested with the input. +- A function: It's called with the input and must return a truthy value to match. +- An array of Conditions: At least one of the Conditions must match. +- An object: All properties must match. Each property has a defined behavior. + +`{ test: Condition }`: The Condition must match. The convention is to provide a RegExp or array of RegExps here, but it's not enforced. + +`{ include: Condition }`: The Condition must match. The convention is to provide a string or array of strings here, but it's not enforced. + +`{ exclude: Condition }`: The Condition must NOT match. The convention is to provide a string or array of strings here, but it's not enforced. + +`{ and: [Condition] }`: All Conditions must match. + +`{ or: [Condition] }`: Any Condition must match. + +`{ not: [Condition] }`: All Conditions must NOT match. + +__Example:__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + test: /\.css$/, + include: [ + path.resolve(__dirname, 'app/styles'), + path.resolve(__dirname, 'vendor/styles') + ] + } + ] + } +}; +``` + + +## `UseEntry` + +`object` + +It must have a `loader` property being a string. It is resolved relative to the configuration [`context`](/configuration/entry-context#context) with the loader resolving options ([resolveLoader](/configuration/resolve#resolveloader)). + +It can have an `options` property being a string or object. This value is passed to the loader, which should interpret it as loader options. + +For compatibility a `query` property is also possible, which is an alias for the `options` property. Use the `options` property instead. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + rules: [ + { + loader: 'css-loader', + options: { + modules: true + } + } + ] + } +}; +``` + +Note that webpack needs to generate a unique module identifier from the resource and all loaders including options. It tries to do this with a `JSON.stringify` of the options object. This is fine in 99.9% of cases, but may be not unique if you apply the same loaders with different options to the resource and the options have some stringified values. + +It also breaks if the options object cannot be stringified (i.e. circular JSON). Because of this you can have a `ident` property in the options object which is used as unique identifier. + + +## Module Contexts + +> Avoid using these options as they are __deprecated__ and will soon be removed. + +These options describe the default settings for the context created when a dynamic dependency is encountered. + +Example for an `unknown` dynamic dependency: `require`. + +Example for an `expr` dynamic dependency: `require(expr)`. + +Example for an `wrapped` dynamic dependency: `require('./templates/' + expr)`. + +Here are the available options with their [defaults](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js): + +__webpack.config.js__ + +```javascript +module.exports = { + //... + module: { + exprContextCritical: true, + exprContextRecursive: true, + exprContextRegExp: false, + exprContextRequest: '.', + unknownContextCritical: true, + unknownContextRecursive: true, + unknownContextRegExp: false, + unknownContextRequest: '.', + wrappedContextCritical: false, + wrappedContextRecursive: true, + wrappedContextRegExp: /.*/, + strictExportPresence: false // since webpack 2.3.0 + } +}; +``` + +T> You can use the `ContextReplacementPlugin` to modify these values for individual dependencies. This also removes the warning. + +A few use cases: + +- Warn for dynamic dependencies: `wrappedContextCritical: true`. +- `require(expr)` should include the whole directory: `exprContextRegExp: /^\.\//` +- `require('./templates/' + expr)` should not include subdirectories by default: `wrappedContextRecursive: false` +- `strictExportPresence` makes missing exports an error instead of warning + + +# Resolve + +These options change how modules are resolved. webpack provides reasonable defaults, but it is possible to change the resolving in detail. Have a look at [Module Resolution](/concepts/module-resolution) for more explanation of how the resolver works. + + +## `resolve` + +`object` + +Configure how modules are resolved. For example, when calling `import "lodash"` in ES2015, the `resolve` options can change where webpack goes to look for `"lodash"` (see [`modules`](#resolve-modules)). + + +### `resolve.alias` + +`object` + +Create aliases to `import` or `require` certain modules more easily. For example, to alias a bunch of commonly used `src/` folders: + +```js +module.exports = { + //... + resolve: { + alias: { + Utilities: path.resolve(__dirname, 'src/utilities/'), + Templates: path.resolve(__dirname, 'src/templates/') + } + } +}; +``` + +Now, instead of using relative paths when importing like so: + +```js +import Utility from '../../utilities/utility'; +``` + +you can use the alias: + +```js +import Utility from 'Utilities/utility'; +``` + +A trailing `$` can also be added to the given object's keys to signify an exact match: + +```js +module.exports = { + //... + resolve: { + alias: { + xyz$: path.resolve(__dirname, 'path/to/file.js') + } + } +}; +``` + +which would yield these results: + +```js +import Test1 from 'xyz'; // Exact match, so path/to/file.js is resolved and imported +import Test2 from 'xyz/file.js'; // Not an exact match, normal resolution takes place +``` + +The following table explains other cases: + +| `alias:` | `import "xyz"` | `import "xyz/file.js"` | +| ----------------------------------- | ------------------------------------- | ----------------------------------- | +| `{}` | `/abc/node_modules/xyz/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | error | +| `{ xyz$: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "./dir/file.js" }` | `/abc/dir/file.js` | error | +| `{ xyz$: "./dir/file.js" }` | `/abc/dir/file.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "/some/dir" }` | `/some/dir/index.js` | `/some/dir/file.js` | +| `{ xyz$: "/some/dir" }` | `/some/dir/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "./dir" }` | `/abc/dir/index.js` | `/abc/dir/file.js` | +| `{ xyz: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/modu/file.js` | +| `{ xyz$: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/xyz/file.js` | +| `{ xyz: "modu/some/file.js" }` | `/abc/node_modules/modu/some/file.js` | error | +| `{ xyz: "modu/dir" }` | `/abc/node_modules/modu/dir/index.js` | `/abc/node_modules/dir/file.js` | +| `{ xyz: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/dir/file.js` | +| `{ xyz$: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/file.js` | + +`index.js` may resolve to another file if defined in the `package.json`. + +`/abc/node_modules` may resolve in `/node_modules` too. + + +### `resolve.aliasFields` + +`array` + +Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec). Default: + +```js +module.exports = { + //... + resolve: { + aliasFields: ['browser'] + } +}; +``` + + +### `resolve.cacheWithContext` + +`boolean` (since webpack 3.1.0) + +If unsafe cache is enabled, includes `request.context` in the cache key. This option is taken into account by the [`enhanced-resolve`](https://github.com/webpack/enhanced-resolve/) module. Since webpack 3.1.0 context in resolve caching is ignored when resolve or resolveLoader plugins are provided. This addresses a performance regression. + + +### `resolve.descriptionFiles` + +`array` + +The JSON files to use for descriptions. Default: + +```js +module.exports = { + //... + resolve: { + descriptionFiles: ['package.json'] + } +}; +``` + + +### `resolve.enforceExtension` + +`boolean` + +If `true`, it will not allow extension-less files. So by default `require('./foo')` works if `./foo` has a `.js` extension, but with this enabled only `require('./foo.js')` will work. Default: + +```js +module.exports = { + //... + resolve: { + enforceExtension: false + } +}; +``` + + +### `resolve.enforceModuleExtension` + +`boolean` + +Whether to require to use an extension for modules (e.g. loaders). Default: + +```js +module.exports = { + //... + resolve: { + enforceModuleExtension: false + } +}; +``` + + +### `resolve.extensions` + +`array` + +Automatically resolve certain extensions. This defaults to: + +```js +module.exports = { + //... + resolve: { + extensions: ['.wasm', '.mjs', '.js', '.json'] + } +}; +``` + +which is what enables users to leave off the extension when importing: + +```js +import File from '../path/to/file'; +``` + +W> Using this will __override the default array__, meaning that webpack will no longer try to resolve modules using the default extensions. For modules that are imported with their extension, e.g. `import SomeFile from "./somefile.ext"`, to be properly resolved, a string containing "\*" must be included in the array. + + +### `resolve.mainFields` + +`array` + +When importing from an npm package, e.g. `import * as D3 from "d3"`, this option will determine which fields in its `package.json` are checked. The default values will vary based upon the [`target`](/concepts/targets) specified in your webpack configuration. + +When the `target` property is set to `webworker`, `web`, or left unspecified: + + +```js +module.exports = { + //... + resolve: { + mainFields: ['browser', 'module', 'main'] + } +}; +``` + +For any other target (including `node`): + +```js +module.exports = { + //... + resolve: { + mainFields: ['module', 'main'] + } +}; +``` + +For example, the `package.json` of [D3](https://d3js.org/) contains these fields: + +```json +{ + "main": "build/d3.Node.js", + "browser": "build/d3.js", + "module": "index" +} +``` + +This means that when we `import * as D3 from "d3"` this will really resolve to the file in the `browser` property. The `browser` property takes precedence here because it's the first item in `mainFields`. Meanwhile, a Node.js application bundled by webpack will resolve by default to the file in the `module` field. + + +### `resolve.mainFiles` + +`array` + +The filename to be used while resolving directories. Default: + +```js +module.exports = { + //... + resolve: { + mainFiles: ['index'] + } +}; +``` + + +### `resolve.modules` + +`array` + +Tell webpack what directories should be searched when resolving modules. + +Absolute and relative paths can both be used, but be aware that they will behave a bit differently. + +A relative path will be scanned similarly to how Node scans for `node_modules`, by looking through the current directory as well as its ancestors (i.e. `./node_modules`, `../node_modules`, and on). + +With an absolute path, it will only search in the given directory. + +`resolve.modules` defaults to: + +```js +module.exports = { + //... + resolve: { + modules: ['node_modules'] + } +}; +``` + +If you want to add a directory to search in that takes precedence over `node_modules/`: + +```js +module.exports = { + //... + resolve: { + modules: [path.resolve(__dirname, 'src'), 'node_modules'] + } +}; +``` + + +### `resolve.unsafeCache` + +`regex` `array` `boolean` + +Enable aggressive, but __unsafe__, caching of modules. Passing `true` will cache everything. Default: + +```js +module.exports = { + //... + resolve: { + unsafeCache: true + } +}; +``` + +A regular expression, or an array of regular expressions, can be used to test file paths and only cache certain modules. For example, to only cache utilities: + +```js +module.exports = { + //... + resolve: { + unsafeCache: /src\/utilities/ + } +}; +``` + +W> Changes to cached paths may cause failure in rare cases. + + +### `resolve.plugins` + +A list of additional resolve plugins which should be applied. It allows plugins such as [`DirectoryNamedWebpackPlugin`](https://www.npmjs.com/package/directory-named-webpack-plugin). + +```js +module.exports = { + //... + resolve: { + plugins: [ + new DirectoryNamedWebpackPlugin() + ] + } +}; +``` + + +### `resolve.symlinks` + +`boolean` + +Whether to resolve symlinks to their symlinked location. + +When enabled, symlinked resources are resolved to their _real_ path, not their symlinked location. Note that this may cause module resolution to fail when using tools that symlink packages (like `npm link`). + +`resolve.symlinks` defaults to: + +```js +module.exports = { + //... + resolve: { + symlinks: true + } +}; +``` + + +### `resolve.cachePredicate` + +`function` + +A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. Default: + +```js +module.exports = { + //... + resolve: { + cachePredicate: function() { return true; } + } +}; +``` + + +## `resolveLoader` + +`object` + +This set of options is identical to the `resolve` property set above, but is used only to resolve webpack's [loader](/concepts/loaders) packages. Default: + +```js +module.exports = { + //... + resolveLoader: { + modules: [ 'node_modules' ], + extensions: [ '.js', '.json' ], + mainFields: [ 'loader', 'main' ] + } +}; +``` + +T> Note that you can use alias here and other features familiar from resolve. For example `{ txt: 'raw-loader' }` would shim `txt!templates/demo.txt` to use `raw-loader`. + + +### `resolveLoader.moduleExtensions` + +`array` + +The extensions/suffixes that are used when resolving loaders. Since version two, we [strongly recommend](/migrate/3/#automatic-loader-module-name-extension-removed) using the full name, e.g. `example-loader`, as much as possible for clarity. However, if you really wanted to exclude the `-loader` bit, i.e. just use `example`, you can use this option to do so: + +```js +module.exports = { + //... + resolveLoader: { + moduleExtensions: [ '-loader' ] + } +}; +``` + + +# Optimization + +Since version 4 webpack runs optimizations for you depending on the chosen [`mode`](/concepts/mode/), still all optimizations are available for manual configuration and overrides. + + +## `optimization.minimize` + +`boolean` + +Tell webpack to minimize the bundle using the [TerserPlugin](/plugins/terser-webpack-plugin/). + +This is `true` by default in `production` mode. + +__webpack.config.js__ + + +```js +module.exports = { + //... + optimization: { + minimize: false + } +}; +``` + +T> Learn how [mode](/concepts/mode/) works. + +## `optimization.minimizer` + +`[TerserPlugin]` + +Allows you to override the default minimizer by providing a different one or more customized [TerserPlugin](/plugins/terser-webpack-plugin/) instances. + +__webpack.config.js__ + + +```js +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + //... + optimization: { + minimizer: [ + new TerserPlugin({ /* your config */ }) + ] + } +}; +``` + +## `optimization.splitChunks` + +`object` + +By default webpack v4+ provides new common chunks strategies out of the box for dynamically imported modules. See available options for configuring this behavior in the [SplitChunksPlugin](/plugins/split-chunks-plugin/) page. + +## `optimization.runtimeChunk` + +`object` `string` `boolean` + +Setting `optimization.runtimeChunk` to `true` or `"multiple"` adds an additional chunk to each entrypoint containing only the runtime. This setting is an alias for: + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: entrypoint => `runtime~${entrypoint.name}` + } + } +}; +``` + +The value `"single"` instead creates a runtime file to be shared for all generated chunks. This setting is an alias for: + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: 'runtime' + } + } +}; +``` + +By setting `optimization.runtimeChunk` to `object` it is only possible to provide the `name` property which stands for the name or name factory for the runtime chunks. + +Default is `false`: each entry chunk embeds runtime. + +W> Imported modules are initialized for each runtime chunk separately, so if you include multiple entry points on a page, beware of this behavior. You will probably want to set it to `single` or use another configuration that allows you to only have one runtime instance. + +__webpack.config.js__ + + +```js +module.exports = { + //... + optimization: { + runtimeChunk: { + name: entrypoint => `runtimechunk~${entrypoint.name}` + } + } +}; +``` + +## `optimization.noEmitOnErrors` + +`boolean` + +Use the `optimization.noEmitOnErrors` to skip the emitting phase whenever there are errors while compiling. This ensures that no erroring assets are emitted. The `emitted` flag in the stats is `false` for all assets. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + noEmitOnErrors: true + } +}; +``` + +W> If you are using webpack [CLI](/api/cli/), the webpack process will not exit with an error code while this plugin is enabled. If you want webpack to "fail" when using the CLI, please check out the [`bail` option](/api/cli/#advanced-options). + +## `optimization.namedModules` + +`boolean: false` + +Tells webpack to use readable module identifiers for better debugging. When `optimization.namedModules` is not set in webpack config, webpack will enable it by default for [mode](/concepts/mode/) `development` and disable for [mode](/concepts/mode/) `production`. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + namedModules: true + } +}; +``` + +## `optimization.namedChunks` + +`boolean: false` + +Tells webpack to use readable chunk identifiers for better debugging. This option is enabled by default for [mode](/concepts/mode/) `development` and disabled for [mode](/concepts/mode/) `production` if no option is provided in webpack config. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + namedChunks: true + } +}; +``` + +## `optimization.moduleIds` + +`bool: false` `string: natural, named, hashed, size, total-size` + +Tells webpack which algorithm to use when choosing module ids. Setting `optimization.moduleIds` to `false` tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin. By default `optimization.moduleIds` is set to `false`. + +The following string values are supported: + +Option | Description +--------------------- | ----------------------- +`natural` | Numeric ids in order of usage. +`named` | Readable ids for better debugging. +`hashed` | Short hashes as ids for better long term caching. +`size` | Numeric ids focused on minimal initial download size. +`total-size` | numeric ids focused on minimal total download size. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + moduleIds: 'hashed' + } +}; +``` + +## `optimization.nodeEnv` + +`string` `bool: false` + +Tells webpack to set `process.env.NODE_ENV` to a given string value. `optimization.nodeEnv` uses [DefinePlugin](/plugins/define-plugin/) unless set to `false`. `optimization.nodeEnv` __defaults__ to [mode](/concepts/mode/) if set, else falls back to `"production"`. + +Possible values: + +- any string: the value to set `process.env.NODE_ENV` to. +- false: do not modify/set the value of `process.env.NODE_ENV`. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + nodeEnv: 'production' + } +}; +``` + +## `optimization.mangleWasmImports` + +`bool: false` + +When set to `true` tells webpack to reduce the size of WASM by changing imports to shorter strings. It mangles module and export names. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + mangleWasmImports: true + } +}; +``` + +## `optimization.removeAvailableModules` + +`bool: true` + +Tells webpack to detect and remove modules from chunks when these modules are already included in all parents. Setting `optimization.removeAvailableModules` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + removeAvailableModules: false + } +}; +``` + +## `optimization.removeEmptyChunks` + +`bool: true` + +Tells webpack to detect and remove chunks which are empty. Setting `optimization.removeEmptyChunks` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + removeEmptyChunks: false + } +}; +``` + +## `optimization.mergeDuplicateChunks` + +`bool: true` + +Tells webpack to merge chunks which contain the same modules. Setting `optimization.mergeDuplicateChunks` to `false` will disable this optimization. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + mergeDuplicateChunks: false + } +}; +``` + +## `optimization.flagIncludedChunks` + +`bool` + +Tells webpack to determine and flag chunks which are subsets of other chunks in a way that subsets don’t have to be loaded when the bigger chunk has been already loaded. By default `optimization.flagIncludedChunks` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + flagIncludedChunks: true + } +}; +``` + +## `optimization.occurrenceOrder` + +`bool` + +Tells webpack to figure out an order of modules which will result in the smallest initial bundle. By default `optimization.occurrenceOrder` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + occurrenceOrder: false + } +}; +``` + +## `optimization.providedExports` + +`bool` + +Tells webpack to figure out which exports are provided by modules to generate more efficient code for `export * from ...`. By default `optimization.providedExports` is enabled. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + providedExports: false + } +}; +``` + +## `optimization.usedExports` + +`bool` + +Tells webpack to determine used exports for each module. This depends on [`optimization.providedExports`](#optimization-occurrenceorder). Information collected by `optimization.usedExports` is used by other optimizations or code generation i.e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible. +Dead code elimination in minimizers will benefit from this and can remove unused exports. +By default `optimization.usedExports` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + usedExports: true + } +}; +``` + +## `optimization.concatenateModules` + +`bool` + +Tells webpack to find segments of the module graph which can be safely concatenated into a single module. Depends on [`optimization.providedExports`](#optimization-providedexports) and [`optimization.usedExports`](#optimization-usedexports). +By default `optimization.concatenateModules` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + concatenateModules: true + } +}; +``` + +## `optimization.sideEffects` + +`bool` + +Tells webpack to recognise the [`sideEffects`](https://github.com/webpack/webpack/blob/master/examples/side-effects/README.md) flag in `package.json` or rules to skip over modules which are flagged to contain no side effects when exports are not used. + +__package.json__ + +``` json +{ + "name": "awesome npm module", + "version": "1.0.0", + "sideEffects": false +} +``` + +T> Please note that `sideEffects` should be in the npm module's `package.json` file and doesn't mean that you need to set `sideEffects` to `false` in your own project's `package.json` which requires that big module. + +`optimization.sideEffects` depends on [`optimization.providedExports`](#optimization-providedexports) to be enabled. This dependency has a build time cost, but eliminating modules has positive impact on performance because of less code generation. Effect of this optimization depends on your codebase, try it for possible performance wins. + +By default `optimization.sideEffects` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + sideEffects: true + } +}; +``` + +## `optimization.portableRecords` + +`bool` + +`optimization.portableRecords` tells webpack to generate records with relative paths to be able to move the context folder. + +By default `optimization.portableRecords` is disabled. Automatically enabled if at least one of the records options provided to webpack config: [`recordsPath`](/configuration/other-options/#recordspath), [`recordsInputPath`](/configuration/other-options/#recordsinputpath), [`recordsOutputPath`](/configuration/other-options/#recordsoutputpath). + +__webpack.config.js__ + +```js +module.exports = { + //... + optimization: { + portableRecords: true + } +}; +``` + + +# Plugins + +The `plugins` option is used to customize the webpack build process in a variety of ways. webpack comes with a variety built-in plugins available under `webpack.[plugin-name]`. See [Plugins page](/plugins) for a list of plugins and documentation but note that there are a lot more out in the community. + +T> Note: This page only discusses using plugins, however if you are interested in writing your own please visit [Writing a Plugin](/development/how-to-write-a-plugin/). + + +## `plugins` + +`array` + +A list of webpack plugins. For example, [`DefinePlugin`](/plugins/define-plugin/) allows you to create global constants which can be configured at compile time. This can be useful for allowing different behavior between development builds and release builds. + +```js +module.exports = { + //... + plugins: [ + new webpack.DefinePlugin({ + // Definitions... + }) + ] +}; +``` + +A more complex example, using multiple plugins, might look something like this: + +```js +var webpack = require('webpack'); +// importing plugins that do not come by default in webpack +var ExtractTextPlugin = require('extract-text-webpack-plugin'); +var DashboardPlugin = require('webpack-dashboard/plugin'); + +// adding plugins to your configuration +module.exports = { + //... + plugins: [ + new ExtractTextPlugin({ + filename: 'build.min.css', + allChunks: true, + }), + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + // compile time plugins + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': '"production"', + }), + // webpack-dev-server enhancement plugins + new DashboardPlugin(), + new webpack.HotModuleReplacementPlugin(), + ] +}; +``` + + +# DevServer + +[webpack-dev-server](https://github.com/webpack/webpack-dev-server) can be used to quickly develop an application. See the [development guide](/guides/development/) to get started. + +This page describes the options that affect the behavior of webpack-dev-server (short: dev-server). + +T> Options that are compatible with [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) have 🔑 next to them. + + +## `devServer` + +`object` + +This set of options is picked up by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) and can be used to change its behavior in various ways. Here's a simple example that gzips and serves everything from our `dist/` directory in the project root: + +__webpack.config.js__ + +```javascript +var path = require('path'); + +module.exports = { + //... + devServer: { + contentBase: path.join(__dirname, 'dist'), + compress: true, + port: 9000 + } +}; +``` + +When the server is started, there will be a message prior to the list of resolved modules: + +```bash +http://localhost:9000/ +webpack output is served from /build/ +Content not from webpack is served from /path/to/dist/ +``` + +that will give some background on where the server is located and what it's serving. + +If you're using dev-server through the Node.js API, the options in `devServer` will be ignored. Pass the options as a second parameter instead: `new WebpackDevServer(compiler, {...})`. [See here](https://github.com/webpack/webpack-dev-server/tree/master/examples/api/simple) for an example of how to use webpack-dev-server through the Node.js API. + +W> Be aware that when [exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) only the `devServer` options for the first configuration will be taken into account and used for all the configurations in the array. + +T> If you're having trouble, navigating to the `/webpack-dev-server` route will show where files are served. For example, `http://localhost:9000/webpack-dev-server`. + +## `devServer.after` + +`function (app, server)` + +Provides the ability to execute custom middleware after all other middleware +internally within the server. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + after: function(app, server) { + // do fancy stuff + } + } +}; +``` + +## `devServer.allowedHosts` + +`array` + +This option allows you to whitelist services that are allowed to access the dev server. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + allowedHosts: [ + 'host.com', + 'subdomain.host.com', + 'subdomain2.host.com', + 'host2.com' + ] + } +}; +``` + +Mimicking django's `ALLOWED_HOSTS`, a value beginning with `.` can be used as a subdomain wildcard. `.host.com` will match `host.com`, `www.host.com`, and any other subdomain of `host.com`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + // this achieves the same effect as the first example + // with the bonus of not having to update your config + // if new subdomains need to access the dev server + allowedHosts: [ + '.host.com', + 'host2.com' + ] + } +}; +``` + +To use this option with the CLI pass the `--allowed-hosts` option a comma-delimited string. + +```bash +webpack-dev-server --entry /entry/file --output-path /output/path --allowed-hosts .host.com,host2.com +``` + +## `devServer.before` + +`function (app, server)` + +Provides the ability to execute custom middleware prior to all other middleware +internally within the server. This could be used to define custom handlers, for +example: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + before: function(app, server) { + app.get('/some/path', function(req, res) { + res.json({ custom: 'response' }); + }); + } + } +}; +``` + +## `devServer.bonjour` + +This option broadcasts the server via [ZeroConf](http://www.zeroconf.org/) networking on start + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + bonjour: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --bonjour +``` + + +## `devServer.clientLogLevel` + +`string: 'none' | 'info' | 'error' | 'warning'` + +When using _inline mode_, the console in your DevTools will show you messages e.g. before reloading, before an error or when [Hot Module Replacement](/concepts/hot-module-replacement/) is enabled. Defaults to `info`. + +`devServer.clientLogLevel` may be too verbose, you can turn logging off by setting it to `'none'`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + clientLogLevel: 'none' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --client-log-level none +``` + +## `devServer.color` - CLI only + +`boolean` + +Enables/Disables colors on the console. + +```bash +webpack-dev-server --color +``` + + +## `devServer.compress` + +`boolean` + +Enable [gzip compression](https://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/) for everything served: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + compress: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --compress +``` + + +## `devServer.contentBase` + +`boolean: false` `string` `[string]` `number` + +Tell the server where to serve content from. This is only necessary if you want to serve static files. [`devServer.publicPath`](#devserver-publicpath-) will be used to determine where the bundles should be served from, and takes precedence. + +T> It is recommended to use an absolute path. + +By default it will use your current working directory to serve content. To disable `contentBase` set it to `false`. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + contentBase: path.join(__dirname, 'public') + } +}; +``` + +It is also possible to serve from multiple directories: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + contentBase: [path.join(__dirname, 'public'), path.join(__dirname, 'assets')] + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --content-base /path/to/content/dir +``` + + +## `devServer.disableHostCheck` + +`boolean` + +When set to `true` this option bypasses host checking. __THIS IS NOT RECOMMENDED__ as apps that do not check the host are vulnerable to DNS rebinding attacks. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + disableHostCheck: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --disable-host-check +``` + + +## `devServer.filename` 🔑 + +`string` + +This option lets you reduce the compilations in [lazy mode](#devserver-lazy-). +By default in [lazy mode](#devserver-lazy-), every request results in a new compilation. With `filename`, it's possible to only compile when a certain file is requested. + +If [`output.filename`](/configuration/output/#output-filename) is set to `'bundle.js'` and `devServer.filename` is used like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + output: { + filename: 'bundle.js' + }, + devServer: { + lazy: true, + filename: 'bundle.js' + } +}; +``` + +It will now only compile the bundle when `/bundle.js` is requested. + +T> `filename` has no effect when used without [lazy mode](#devserver-lazy-). + + +## `devServer.headers` 🔑 + +`object` + +Adds headers to all responses: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + headers: { + 'X-Custom-Foo': 'bar' + } + } +}; +``` + + +## `devServer.historyApiFallback` + +`boolean` `object` + +When using the [HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/API/History), the `index.html` page will likely have to be served in place of any `404` responses. `devServer.historyApiFallback` is disabled by default. Enable it by passing: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: true + } +}; +``` + +By passing an object this behavior can be controlled further using options like `rewrites`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: { + rewrites: [ + { from: /^\/$/, to: '/views/landing.html' }, + { from: /^\/subpage/, to: '/views/subpage.html' }, + { from: /./, to: '/views/404.html' } + ] + } + } +}; +``` + +When using dots in your path (common with Angular), you may need to use the `disableDotRule`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + historyApiFallback: { + disableDotRule: true + } + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --history-api-fallback +``` + +For more options and information, see the [connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback) documentation. + + +## `devServer.host` + +`string` + +Specify a host to use. By default this is `localhost`. If you want your server to be accessible externally, specify it like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + host: '0.0.0.0' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --host 0.0.0.0 +``` + + +## `devServer.hot` + +`boolean` + +Enable webpack's [Hot Module Replacement](/concepts/hot-module-replacement/) feature: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + hot: true + } +}; +``` + +T> Note that [`webpack.HotModuleReplacementPlugin`](/plugins/hot-module-replacement-plugin/) is required to fully enable HMR. If `webpack` or `webpack-dev-server` are launched with the `--hot` option, this plugin will be added automatically, so you may not need to add this to your `webpack.config.js`. See the [HMR concepts page](/concepts/hot-module-replacement/) for more information. + + +## `devServer.hotOnly` + +`boolean` + +Enables Hot Module Replacement (see [`devServer.hot`](#devserver-hot)) without page refresh as fallback in case of build failures. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + hotOnly: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --hot-only +``` + + +## `devServer.https` + +`boolean` `object` + +By default dev-server will be served over HTTP. It can optionally be served over HTTP/2 with HTTPS: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + https: true + } +}; +``` + +With the above setting a self-signed certificate is used, but you can provide your own: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + https: { + key: fs.readFileSync('/path/to/server.key'), + cert: fs.readFileSync('/path/to/server.crt'), + ca: fs.readFileSync('/path/to/ca.pem'), + } + } +}; +``` + +This object is passed straight to Node.js HTTPS module, so see the [HTTPS documentation](https://nodejs.org/api/https.html) for more information. + +Usage via the CLI + +```bash +webpack-dev-server --https +``` + +To pass your own certificate via the CLI use the following options + +```bash +webpack-dev-server --https --key /path/to/server.key --cert /path/to/server.crt --cacert /path/to/ca.pem +``` + +## `devServer.index` + +`string` + +The filename that is considered the index file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + index: 'index.html' + } +}; +``` + + +## `devServer.info` - CLI only + +`boolean` + +Output cli information. It is enabled by default. + +```bash +webpack-dev-server --info=false +``` + + +## `devServer.inline` + +`boolean` + +Toggle between the dev-server's two different modes. By default the application will be served with _inline mode_ enabled. This means that a script will be inserted in your bundle to take care of live reloading, and build messages will appear in the browser console. + +It is also possible to use __iframe mode__, which uses an `<iframe>` under a notification bar with messages about the build. To switch to __iframe mode__: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + inline: false + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --inline=false +``` + +T> Inline mode is recommended for [Hot Module Replacement](/plugins/hot-module-replacement-plugin/) as it includes an HMR trigger from the websocket. Polling mode can be used as an alternative, but requires an additional entry point, `'webpack/hot/poll?1000'`. + + +## `devServer.lazy` 🔑 + +`boolean` + +When `devServer.lazy` is enabled, the dev-server will only compile the bundle when it gets requested. This means that webpack will not watch any file changes. We call this __lazy mode__. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + lazy: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --lazy +``` + +T> [`watchOptions`](#devserver-watchoptions-) will have no effect when used with __lazy mode__. + +T> If you use the CLI, make sure __inline mode__ is disabled. + + +## `devServer.noInfo` 🔑 + +`boolean` + +Tells dev-server to supress messages like the webpack bundle information. Errors and warnings will still be shown. `devServer.noInfo` is disabled by default. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + noInfo: true + } +}; +``` + + +## `devServer.open` + +`boolean` `string` + +Tells dev-server to open the browser after server had been started. Disabled by default. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + open: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --open +``` + +If no browser is provided (as shown above), your default browser will be used. To specify a different browser, just pass its name: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + open: 'Chrome' + } +}; +``` + +And via the CLI + +```bash +webpack-dev-server --open 'Chrome' +``` + +T> The browser application name is platform dependent. Don't hard code it in reusable modules. For example, `'Chrome'` is Google Chrome on macOS, `'google-chrome'` on Linux and `'chrome'` on Windows. + + +## `devServer.openPage` + +`string` + +Specify a page to navigate to when opening the browser. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + openPage: '/different/page' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --open-page "/different/page" +``` + + +## `devServer.overlay` + +`boolean` `object: { boolean errors, boolean warnings }` + +Shows a full-screen overlay in the browser when there are compiler errors or warnings. Disabled by default. If you want to show only compiler errors: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + overlay: true + } +}; +``` + +If you want to show warnings as well as errors: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + overlay: { + warnings: true, + errors: true + } + } +}; +``` + + +## `devServer.pfx` + +`string` + +When used via the CLI, a path to an SSL .pfx file. If used in options, it should be the bytestream of the .pfx file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + pfx: '/path/to/file.pfx' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --pfx /path/to/file.pfx +``` + + +## `devServer.pfxPassphrase` + +`string` + +The passphrase to a SSL PFX file. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + pfxPassphrase: 'passphrase' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --pfx-passphrase passphrase +``` + + +## `devServer.port` + +`number` + +Specify a port number to listen for requests on: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + port: 8080 + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --port 8080 +``` + + +## `devServer.proxy` + +`object` `[object, function]` + +Proxying some URLs can be useful when you have a separate API backend development server and you want to send API requests on the same domain. + +The dev-server makes use of the powerful [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) package. Check out its [documentation](https://github.com/chimurai/http-proxy-middleware#options) for more advanced usages. Note that some of `http-proxy-middleware`'s features do not require a `target` key, e.g. its `router` feature, but you will still need to include a `target` key in your config here, otherwise `webpack-dev-server` won't pass it along to `http-proxy-middleware`). + +With a backend on `localhost:3000`, you can use this to enable proxying: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': 'http://localhost:3000' + } + } +}; +``` + +A request to `/api/users` will now proxy the request to `http://localhost:3000/api/users`. + +If you don't want `/api` to be passed along, we need to rewrite the path: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'http://localhost:3000', + pathRewrite: {'^/api' : ''} + } + } + } +}; +``` + +A backend server running on HTTPS with an invalid certificate will not be accepted by default. If you want to, modify your config like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'https://other-server.example.com', + secure: false + } + } + } +}; +``` + +Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a function. + +In the function you get access to the request, response and proxy options. It must return either `false` or a path that will be served instead of continuing to proxy the request. + +E.g. for a browser request, you want to serve a HTML page, but for an API request you want to proxy it. You could do something like this: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': { + target: 'http://localhost:3000', + bypass: function(req, res, proxyOptions) { + if (req.headers.accept.indexOf('html') !== -1) { + console.log('Skipping proxy for browser request.'); + return '/index.html'; + } + } + } + } + } +}; +``` + +If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a `context` property: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: [{ + context: ['/auth', '/api'], + target: 'http://localhost:3000', + }] + } +}; +``` + +Note that requests to root won't be proxied by default. To enable root proxying, the `devServer.index` option should be specified as a falsy value: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + index: '', // specify to enable root proxying + host: '...', + contentBase: '...', + proxy: { + context: () => true, + target: 'http://localhost:1234' + } + } +}; +``` + +The origin of the host header is kept when proxying by default, you can set `changeOrigin` to `true` to override this behaviour. It is useful in some cases like using [name-based virtual hosted sites](https://en.wikipedia.org/wiki/Virtual_hosting#Name-based). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + proxy: { + '/api': 'http://localhost:3000', + changeOrigin: true + } + } +}; +``` + +## `devServer.progress` - CLI only + +`boolean` + +Output running progress to console. + +```bash +webpack-dev-server --progress +``` + + +## `devServer.public` + +`string` + +When using _inline mode_ and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on `window.location`, but if that fails you'll need to use this. + +For example, the dev-server is proxied by nginx, and available on `myapp.test`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + public: 'myapp.test:80' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --public myapp.test:80 +``` + + +## `devServer.publicPath` 🔑 + +`string` + +The bundled files will be available in the browser under this path. + +Imagine that the server is running under `http://localhost:8080` and [`output.filename`](/configuration/output/#output-filename) is set to `bundle.js`. By default the `devServer.publicPath` is `'/'`, so your bundle is available as `http://localhost:8080/bundle.js`. + +Change `devServer.publicPath` to put bundle under specific directory: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + publicPath: '/assets/' + } +}; +``` + +The bundle will now be available as `http://localhost:8080/assets/bundle.js`. + +T> Make sure `devServer.publicPath` always starts and ends with a forward slash. + +It is also possible to use a full URL. This is necessary for [Hot Module Replacement](/concepts/hot-module-replacement/). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + publicPath: 'http://localhost:8080/assets/' + } +}; +``` + +The bundle will also be available as `http://localhost:8080/assets/bundle.js`. + +T> It is recommended that `devServer.publicPath` is the same as [`output.publicPath`](/configuration/output/#output-publicpath). + + +## `devServer.quiet` 🔑 + +`boolean` + +With `devServer.quiet` enabled, nothing except the initial startup information will be written to the console. This also means that errors or warnings from webpack are not visible. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + quiet: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --quiet +``` + + +## `devServer.setup` + +`function (app, server)` + +W> This option is __deprecated__ in favor of [`devServer.before`](#devserver-before) and will be removed in v3.0.0. + +Here you can access the Express app object and add your own custom middleware to it. +For example, to define custom handlers for some paths: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + setup: function(app, server) { + app.get('/some/path', function(req, res) { + res.json({ custom: 'response' }); + }); + } + } +}; +``` + + +## `devServer.socket` + +`string` + +The Unix socket to listen to (instead of a host). + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + socket: 'socket' + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --socket socket +``` + + +## `devServer.staticOptions` + +It is possible to configure advanced options for serving static files from `contentBase`. See the [Express documentation](http://expressjs.com/en/4x/api.html#express.static) for the possible options. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + staticOptions: { + redirect: false + } + } +}; +``` + +T> This only works when using [`devServer.contentBase`](#devserver-contentbase) as a `string`. + + +## `devServer.stats` 🔑 + +`string: 'none' | 'errors-only' | 'minimal' | 'normal' | 'verbose'` `object` + +This option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you want some bundle information, but not all of it. + +To show only errors in your bundle: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + stats: 'errors-only' + } +}; +``` + +For more information, see the [__stats documentation__](/configuration/stats/). + +T> This option has no effect when used with `quiet` or `noInfo`. + + +## `devServer.stdin` - CLI only + +`boolean` + +This option closes the server when stdin ends. + +```bash +webpack-dev-server --stdin +``` + + +## `devServer.useLocalIp` + +`boolean` + +This option lets the browser open with your local IP. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + useLocalIp: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --useLocalIp +``` + + +## `devServer.watchContentBase` + +`boolean` + +Tell dev-server to watch the files served by the [`devServer.contentBase`](#devserver-contentbase) option. It is disabled by default. When enabled, file changes will trigger a full page reload. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + watchContentBase: true + } +}; +``` + +Usage via the CLI + +```bash +webpack-dev-server --watch-content-base +``` + + +## `devServer.watchOptions` 🔑 + +`object` + +Control options related to watching the files. + +webpack uses the file system to get notified of file changes. In some cases this does not work. For example, when using Network File System (NFS). [Vagrant](https://www.vagrantup.com/) also has a lot of problems with this. In these cases, use polling: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + devServer: { + watchOptions: { + poll: true + } + } +}; +``` + +If this is too heavy on the file system, you can change this to an integer to set the interval in milliseconds. + +See [WatchOptions](/configuration/watch/) for more options. + + +# Devtool + +This option controls if and how source maps are generated. + +Use the [`SourceMapDevToolPlugin`](/plugins/source-map-dev-tool-plugin) for a more fine grained configuration. See the [`source-map-loader`](/loaders/source-map-loader) to deal with existing source maps. + + +## `devtool` + +`string` `false` + +Choose a style of [source mapping](http://blog.teamtreehouse.com/introduction-source-maps) to enhance the debugging process. These values can affect build and rebuild speed dramatically. + +T> The webpack repository contains an [example showing the effect of all `devtool` variants](https://github.com/webpack/webpack/tree/master/examples/source-map). Those examples will likely help you to understand the differences. + +T> Instead of using the `devtool` option you can also use `SourceMapDevToolPlugin`/`EvalSourceMapDevToolPlugin` directly as it has more options. Never use both the `devtool` option and plugin together. The `devtool` option adds the plugin internally so you would end up with the plugin applied twice. + +devtool | build | rebuild | production | quality +------------------------------ | ----- | ------- | ---------- | ----------------------------- +(none) | +++ | +++ | yes | bundled code +eval | +++ | +++ | no | generated code +cheap-eval-source-map | + | ++ | no | transformed code (lines only) +cheap-module-eval-source-map | o | ++ | no | original source (lines only) +eval-source-map | -- | + | no | original source +cheap-source-map | + | o | yes | transformed code (lines only) +cheap-module-source-map | o | - | yes | original source (lines only) +inline-cheap-source-map | + | o | no | transformed code (lines only) +inline-cheap-module-source-map | o | - | no | original source (lines only) +source-map | -- | -- | yes | original source +inline-source-map | -- | -- | no | original source +hidden-source-map | -- | -- | yes | original source +nosources-source-map | -- | -- | yes | without source content + +T> `+++` super fast, `++` fast, `+` pretty fast, `o` medium, `-` pretty slow, `--` slow + +Some of these values are suited for development and some for production. For development you typically want fast Source Maps at the cost of bundle size, but for production you want separate Source Maps that are accurate and support minimizing. + +W> There are some issues with Source Maps in Chrome. [We need your help!](https://github.com/webpack/webpack/issues/3165). + +T> See [`output.sourceMapFilename`](/configuration/output#output-sourcemapfilename) to customize the filenames of generated Source Maps. + + +### Qualities + +`bundled code` - You see all generated code as a big blob of code. You don't see modules separated from each other. + +`generated code` - You see each module separated from each other, annotated with module names. You see the code generated by webpack. Example: Instead of `import {test} from "module"; test();` you see something like `var module__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); module__WEBPACK_IMPORTED_MODULE_1__.a();`. + +`transformed code` - You see each module separated from each other, annotated with module names. You see the code before webpack transforms it, but after Loaders transpile it. Example: Instead of `import {test} from "module"; class A extends test {}` you see something like `import {test} from "module"; var A = function(_test) { ... }(test);` + +`original source` - You see each module separated from each other, annotated with module names. You see the code before transpilation, as you authored it. This depends on Loader support. + +`without source content` - Contents for the sources are not included in the Source Maps. Browsers usually try to load the source from the webserver or filesystem. You have to make sure to set [`output.devtoolModuleFilenameTemplate`](/configuration/output/#output-devtoolmodulefilenametemplate) correctly to match source urls. + +`(lines only)` - Source Maps are simplified to a single mapping per line. This usually means a single mapping per statement (assuming you author is this way). This prevents you from debugging execution on statement level and from settings breakpoints on columns of a line. Combining with minimizing is not possible as minimizers usually only emit a single line. + + +### Development + +The following options are ideal for development: + +`eval` - Each module is executed with `eval()` and `//@ sourceURL`. This is pretty fast. The main disadvantage is that it doesn't display line numbers correctly since it gets mapped to transpiled code instead of the original code (No Source Maps from Loaders). + +`eval-source-map` - Each module is executed with `eval()` and a SourceMap is added as a DataUrl to the `eval()`. Initially it is slow, but it provides fast rebuild speed and yields real files. Line numbers are correctly mapped since it gets mapped to the original code. It yields the best quality SourceMaps for development. + +`cheap-eval-source-map` - Similar to `eval-source-map`, each module is executed with `eval()`. It is "cheap" because it doesn't have column mappings, it only maps line numbers. It ignores SourceMaps from Loaders and only display transpiled code similar to the `eval` devtool. + +`cheap-module-eval-source-map` - Similar to `cheap-eval-source-map`, however, in this case Source Maps from Loaders are processed for better results. However Loader Source Maps are simplified to a single mapping per line. + +### Special cases + +The following options are not ideal for development nor production. They are needed for some special cases, i. e. for some 3rd party tools. + +`inline-source-map` - A SourceMap is added as a DataUrl to the bundle. + +`cheap-source-map` - A SourceMap without column-mappings ignoring loader Source Maps. + +`inline-cheap-source-map` - Similar to `cheap-source-map` but SourceMap is added as a DataUrl to the bundle. + +`cheap-module-source-map` - A SourceMap without column-mappings that simplifies loader Source Maps to a single mapping per line. + +`inline-cheap-module-source-map` - Similar to `cheap-module-source-map` but SourceMap is added as a DataUrl to the bundle. + + +### Production + +These options are typically used in production: + +`(none)` (Omit the `devtool` option) - No SourceMap is emitted. This is a good option to start with. + +`source-map` - A full SourceMap is emitted as a separate file. It adds a reference comment to the bundle so development tools know where to find it. + +W> You should configure your server to disallow access to the Source Map file for normal users! + +`hidden-source-map` - Same as `source-map`, but doesn't add a reference comment to the bundle. Useful if you only want SourceMaps to map error stack traces from error reports, but don't want to expose your SourceMap for the browser development tools. + +W> You should not deploy the Source Map file to the webserver. Instead only use it for error report tooling. + +`nosources-source-map` - A SourceMap is created without the `sourcesContent` in it. It can be used to map stack traces on the client without exposing all of the source code. You can deploy the Source Map file to the webserver. + +W> It still exposes filenames and structure for decompiling, but it doesn't expose the original code. + +T> When using the `terser-webpack-plugin` you must provide the `sourceMap: true` option to enable SourceMap support. + + +# Target + +webpack can compile for multiple environments or _targets_. To understand what a `target` is in detail, read through [the targets concept page](/concepts/targets/). + +## `target` + +`string | function (compiler)` + +Instructs webpack to target a specific environment. + + +### `string` + +The following string values are supported via [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js): + +Option | Description +--------------------- | ----------------------- +`async-node` | Compile for usage in a Node.js-like environment (uses `fs` and `vm` to load chunks asynchronously) +`electron-main` | Compile for [Electron](https://electronjs.org/) for main process. +`electron-renderer` | Compile for [Electron](https://electronjs.org/) for renderer process, providing a target using `JsonpTemplatePlugin`, `FunctionModulePlugin` for browser environments and `NodeTargetPlugin` and `ExternalsPlugin` for CommonJS and Electron built-in modules. +`node` | Compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks) +`node-webkit` | Compile for usage in WebKit and uses JSONP for chunk loading. Allows importing of built-in Node.js modules and [`nw.gui`](http://docs.nwjs.io/en/latest/) (experimental) +`web` | Compile for usage in a browser-like environment __(default)__ +`webworker` | Compile as WebWorker + +For example, when the `target` is set to `"electron-main"`, webpack includes multiple electron specific variables. For more information on which templates and externals are used, you can refer to webpack's [source code](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js#L148-L183). + + +### `function` + +If a function is passed, then it will be called with the compiler as a parameter. Set it to a function if none of the predefined targets from the list above meet your needs. + +For example, if you don't want any of the plugins they applied: + +```js +const options = { + target: () => undefined +}; +``` + +Or you can apply specific plugins you want: + +```js +const webpack = require('webpack'); + +const options = { + target: (compiler) => { + compiler.apply( + new webpack.JsonpTemplatePlugin(options.output), + new webpack.LoaderTargetPlugin('web') + ); + } +}; +``` + + +# Watch and WatchOptions + +webpack can watch files and recompile whenever they change. This page explains how to enable this and a couple of tweaks you can make if watching does not work properly for you. + + +## `watch` + +`boolean` + +Turn on watch mode. This means that after the initial build, webpack will continue to watch for changes in any of the resolved files. Watch mode is turned off by default: + +```js +module.exports = { + //... + watch: false +}; +``` + +T> In webpack-dev-server and webpack-dev-middleware watch mode is enabled by default. + + +## `watchOptions` + +`object` + +A set of options used to customize watch mode: + +```js +module.exports = { + //... + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + } +}; +``` + + +## `watchOptions.aggregateTimeout` + +`number` + +Add a delay before rebuilding once the first file changed. This allows webpack to aggregate any other changes made during this time period into one rebuild. Pass a value in milliseconds: + +```js +module.exports = { + //... + watchOptions: { + aggregateTimeout: 300 // The default + } +}; +``` + + +## `watchOptions.ignored` + +For some systems, watching many file systems can result in a lot of CPU or memory usage. It is possible to exclude a huge folder like `node_modules`: + +```js +module.exports = { + //... + watchOptions: { + ignored: /node_modules/ + } +}; +``` + +It is also possible to have and use multiple [anymatch](https://github.com/micromatch/anymatch) patterns: + +```js +module.exports = { + //... + watchOptions: { + ignored: ['files/**/*.js', 'node_modules'] + } +}; +``` + +T> If you use `require.context`, webpack will watch your entire directory. You will need to ignore files and/or directories so that unwanted changes will not trigger a rebuild. + + +## `watchOptions.poll` + +`boolean` `number` + +Turn on [polling](https://whatis.techtarget.com/definition/polling) by passing `true`, or specifying a poll interval in milliseconds: + +```js +module.exports = { + //... + watchOptions: { + poll: 1000 // Check for changes every second + } +}; +``` + +T> If watching does not work for you, try out this option. Watching does not work with NFS and machines in VirtualBox. + + +## `info-verbosity` + +`string`: `none` `info` `verbose` + +Controls verbosity of the lifecycle messaging, e.g. the `Started watching files...` log. Setting `info-verbosity` to `verbose` will also message to console at the beginning and the end of incremental build. `info-verbosity` is set to `info` by default. + +```bash +webpack --watch --info-verbosity verbose +``` + + +## Troubleshooting + +If you are experiencing any issues, please see the following notes. There are a variety of reasons why webpack might miss a file change. + +### Changes Seen But Not Processed + +Verify that webpack is not being notified of changes by running webpack with the --progress flag. If progress shows on save but no files are outputted, it is likely a configuration issue, not a file watching issue. + +```bash +webpack --watch --progress +``` + +### Not Enough Watchers + +Verify that you have enough available watchers in your system. If this value is too low, the file watcher in Webpack won't recognize the changes: + +```bash +cat /proc/sys/fs/inotify/max_user_watches +``` + +Arch users, add `fs.inotify.max_user_watches=524288` to `/etc/sysctl.d/99-sysctl.conf` and then execute `sysctl --system`. Ubuntu users (and possibly others), execute: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`. + +### macOS fsevents Bug + +On macOS, folders can get corrupted in certain scenarios. See [this article](https://github.com/livereload/livereload-site/blob/master/livereload.com/_articles/troubleshooting/os-x-fsevents-bug-may-prevent-monitoring-of-certain-folders.md). + +### Windows Paths + +Because webpack expects absolute paths for many config options such as `__dirname + "/app/folder"` the Windows `\` path separator can break some functionality. + +Use the correct separators. I.e. `path.resolve(__dirname, "app/folder")` or `path.join(__dirname, "app", "folder")`. + +### Vim + +On some machines Vim is preconfigured with the [backupcopy option](http://vimdoc.sourceforge.net/htmldoc/options.html#'backupcopy') set to `auto`. This could potentially cause problems with the system's file watching mechanism. Switching this option to `yes` will make sure a copy of the file is made and the original one overwritten on save. + +`:set backupcopy=yes` + +### Saving in WebStorm + +When using the JetBrains WebStorm IDE, you may find that saving changed files does not trigger the watcher as you might expect. Try disabling the `safe write` option in the settings, which determines whether files are saved to a temporary location first before the originals are overwritten: uncheck `File > Settings... > System Settings > Use "safe write" (save changes to a temporary file first)`. + + +# Externals + +The `externals` configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment. This feature is typically most useful to __library developers__, however there are a variety of applications for it. + +T> __consumer__ here is any end user application that includes the library that you have bundled using webpack. + + +## `externals` + +`string` `object` `function` `regex` + +__Prevent bundling__ of certain `import`ed packages and instead retrieve these _external dependencies_ at runtime. + +For example, to include [jQuery](https://jquery.com/) from a CDN instead of bundling it: + +__index.html__ + +``` html +<script + src="https://code.jquery.com/jquery-3.1.0.js" + integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" + crossorigin="anonymous"> +</script> +``` + +__webpack.config.js__ + +```javascript +module.exports = { + //... + externals: { + jquery: 'jQuery' + } +}; +``` + +This leaves any dependent modules unchanged, i.e. the code shown below will still work: + +```javascript +import $ from 'jquery'; + +$('.my-element').animate(/* ... */); +``` + +The bundle with external dependencies can be used in various module contexts, such as [CommonJS, AMD, global and ES2015 modules](/concepts/modules). The external library may be available in any of these forms: + +- __root__: The library should be available as a global variable (e.g. via a script tag). +- __commonjs__: The library should be available as a CommonJS module. +- __commonjs2__: Similar to the above but where the export is `module.exports.default`. +- __amd__: Similar to `commonjs` but using AMD module system. + +The following syntaxes are accepted... + + +### string + +See the example above. The property name `jquery` indicates that the module `jquery` in `import $ from 'jquery'` should be excluded. In order to replace this module, the value `jQuery` will be used to retrieve a global `jQuery` variable. In other words, when a string is provided it will be treated as `root` (defined above and below). + + +### array + +```javascript +module.exports = { + //... + externals: { + subtract: ['./math', 'subtract'] + } +}; +``` + +`subtract: ['./math', 'subtract']` converts to a parent child construct, where `./math` is the parent module and your bundle only requires the subset under `subtract` variable. + + +### object + +W> An object with `{ root, amd, commonjs, ... }` is only allowed for [`libraryTarget: 'umd'`](/configuration/output/#output-librarytarget). It's not allowed for other library targets. + +```javascript +module.exports = { + //... + externals : { + react: 'react' + }, + + // or + + externals : { + lodash : { + commonjs: 'lodash', + amd: 'lodash', + root: '_' // indicates global variable + } + }, + + // or + + externals : { + subtract : { + root: ['math', 'subtract'] + } + } +}; +``` + +This syntax is used to describe all the possible ways that an external library can be available. `lodash` here is available as `lodash` under AMD and CommonJS module systems but available as `_` in a global variable form. `subtract` here is available via the property `subtract` under the global `math` object (e.g. `window['math']['subtract']`). + + +### function + +It might be useful to define your own function to control the behavior of what you want to externalize from webpack. [webpack-node-externals](https://www.npmjs.com/package/webpack-node-externals), for example, excludes all modules from the `node_modules` directory and provides some options to, for example, whitelist packages. + +It basically comes down to this: + +```javascript +module.exports = { + //... + externals: [ + function(context, request, callback) { + if (/^yourregex$/.test(request)){ + return callback(null, 'commonjs ' + request); + } + callback(); + } + ] +}; +``` + +The `'commonjs ' + request` defines the type of module that needs to be externalized. + + +### regex + +Every dependency that matches the given regular expression will be excluded from the output bundles. + +```javascript +module.exports = { + //... + externals: /^(jquery|\$)$/i +}; +``` + +In this case any dependency named `jQuery`, capitalized or not, or `$` would be externalized. + +### Combining syntaxes + +Sometimes you may want to use a combination of the above syntaxes. This can be done in the following manner: + +```javascript +module.exports = { + //... + externals: [ + { + // String + react: 'react', + // Object + lodash : { + commonjs: 'lodash', + amd: 'lodash', + root: '_' // indicates global variable + }, + // Array + subtract: ['./math', 'subtract'] + }, + // Function + function(context, request, callback) { + if (/^yourregex$/.test(request)){ + return callback(null, 'commonjs ' + request); + } + callback(); + }, + // Regex + /^(jquery|\$)$/i + ] +}; +``` + +For more information on how to use this configuration, please refer to the article on [how to author a library](/guides/author-libraries). + + +# Node + +These options configure whether to polyfill or mock certain [Node.js globals](https://nodejs.org/docs/latest/api/globals.html) and modules. This allows code originally written for the Node.js environment to run in other environments like the browser. + +This feature is provided by webpack's internal [`NodeStuffPlugin`](https://github.com/webpack/webpack/blob/master/lib/NodeStuffPlugin.js) plugin. If the target is "web" (default) or "webworker", the [`NodeSourcePlugin`](https://github.com/webpack/webpack/blob/master/lib/node/NodeSourcePlugin.js) plugin is also activated. + + +## `node` + +`object` + +This is an object where each property is the name of a Node global or module and each value may be one of the following... + +- `true`: Provide a polyfill. +- `"mock"`: Provide a mock that implements the expected interface but has little or no functionality. +- `"empty"`: Provide an empty object. +- `false`: Provide nothing. Code that expects this object may crash with a `ReferenceError`. Code that attempts to import the module using `require('modulename')` may trigger a `Cannot find module "modulename"` error. + +W> Not every Node global supports all four options. The compiler will throw an error for property-value combinations that aren't supported (e.g. `process: 'empty'`). See the sections below for more details. + +These are the defaults: + +```js +module.exports = { + //... + node: { + console: false, + global: true, + process: true, + __filename: 'mock', + __dirname: 'mock', + Buffer: true, + setImmediate: true + + // See "Other node core libraries" for additional options. + } +}; +``` + +Since webpack 3.0.0, the `node` option may be set to `false` to completely turn off the `NodeStuffPlugin` and `NodeSourcePlugin` plugins. + + +## `node.console` + +`boolean | "mock"` + +Default: `false` + +The browser provides a `console` object with a very similar interface to the Node.js `console`, so a polyfill is generally not needed. + + +## `node.process` + +`boolean | "mock"` + +Default: `true` + + +## `node.global` + +`boolean` + +Default: `true` + +See [the source](https://github.com/webpack/webpack/blob/master/buildin/global.js) for the exact behavior of this object. + + +## `node.__filename` + +`boolean | "mock"` + +Default: `"mock"` + +Options: + +- `true`: The filename of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). +- `false`: The regular Node.js `__filename` behavior. The filename of the __output__ file when run in a Node.js environment. +- `"mock"`: The fixed value `"index.js"`. + + +## `node.__dirname` + +`boolean | "mock"` + +Default: `"mock"` + +Options: + +- `true`: The dirname of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). +- `false`: The regular Node.js `__dirname` behavior. The dirname of the __output__ file when run in a Node.js environment. +- `"mock"`: The fixed value `"/"`. + + +## `node.Buffer` + +`boolean | "mock"` + +Default: `true` + + +## `node.setImmediate` + +`boolean | "mock" | "empty"` + +Default: `true` + + +## Other node core libraries + +`boolean | "mock" | "empty"` + +W> This option is only activated (via `NodeSourcePlugin`) when the target is unspecified, "web" or "webworker". + +Polyfills for Node.js core libraries from [`node-libs-browser`](https://github.com/webpack/node-libs-browser) are used if available, when the `NodeSourcePlugin` plugin is enabled. See the list of [Node.js core libraries and their polyfills](https://github.com/webpack/node-libs-browser#readme). + +By default, webpack will polyfill each library if there is a known polyfill or do nothing if there is not one. In the latter case, webpack will behave as if the module name was configured with the `false` value. + +T> To import a built-in module, use [`__non_webpack_require__`](/api/module-variables/#__non_webpack_require__-webpack-specific-), i.e. `__non_webpack_require__('modulename')` instead of `require('modulename')`. + +Example: + +```js +module.exports = { + //... + node: { + dns: 'mock', + fs: 'empty', + path: true, + url: false + } +}; +``` + + +# Performance + +These options allows you to control how webpack notifies you of assets and entry points that exceed a specific file limit. +This feature was inspired by the idea of [webpack Performance Budgets](https://github.com/webpack/webpack/issues/3216). + +## `performance` + +`object` + +Configure how performance hints are shown. For example if you have an asset that is over 250kb, webpack will emit a warning notifying you of this. + + +## `performance.hints` + +`false | "error" | "warning"` + +Turns hints on/off. In addition, tells webpack to throw either an error or a warning when hints are found. This property is set to `"warning"` by default. + +Given an asset is created that is over 250kb: + +```js +module.exports = { + //... + performance: { + hints: false + } +}; +``` + +No hint warnings or errors are shown. + +```js +module.exports = { + //... + performance: { + hints: 'warning' + } +}; +``` + +A warning will be displayed notifying you of a large asset. We recommend something like this for development environments. + +```js +module.exports = { + //... + performance: { + hints: 'error' + } +}; +``` + +An error will be displayed notifying you of a large asset. We recommend using `hints: "error"` during production builds to help prevent deploying production bundles that are too large, impacting webpage performance. + +## `performance.maxEntrypointSize` + +`int` + +An entry point represents all assets that would be utilized during initial load time for a specific entry. This option controls when webpack should emit performance hints based on the maximum entry point size. The default value is `250000` (bytes). + +```js +module.exports = { + //... + performance: { + maxEntrypointSize: 400000 + } +}; +``` + +## `performance.maxAssetSize` + +`int` + +An asset is any emitted file from webpack. This option controls when webpack emits a performance hint based on individual asset size. The default value is `250000` (bytes). + + +```js +module.exports = { + //... + performance: { + maxAssetSize: 100000 + } +}; +``` + +## `performance.assetFilter` + +`Function` + +This property allows webpack to control what files are used to calculate performance hints. The default function is seen below: + +```js +function assetFilter(assetFilename) { + return !(/\.map$/.test(assetFilename)); +} +``` + +You can override this property by passing your own function in: + +```js +module.exports = { + //... + performance: { + assetFilter: function(assetFilename) { + return assetFilename.endsWith('.js'); + } + } +}; +``` + +The example above will only give you performance hints based on `.js` files. + + +# Stats + +The `stats` option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you don't want to use `quiet` or `noInfo` because you want some bundle information, but not all of it. + +T> For webpack-dev-server, this property needs to be in the `devServer` object. + +W> This option does not have any effect when using the Node.js API. + +## `stats` + +`object` `string` + +There are some presets available to use as a shortcut. Use them like this: + +```js +module.exports = { + //... + stats: 'errors-only' +}; +``` + +| Preset | Alternative | Description | +|--------|-------------|-------------| +| `"errors-only"` | _none_ | Only output when errors happen | +| `"minimal"` | _none_ | Only output when errors or new compilation happen | +| `"none"` | `false` | Output nothing | +| `"normal"` | `true` | Standard output | +| `"verbose"` | _none_ | Output everything | + +For more granular control, it is possible to specify exactly what information you want. Please note that all of the options in this object are optional. + +<!-- eslint-skip --> + +```js +module.exports = { + //... + stats: { + // fallback value for stats options when an option is not defined (has precedence over local webpack defaults) + all: undefined, + + // Add asset Information + assets: true, + + // Sort assets by a field + // You can reverse the sort with `!field`. + // Some possible values: 'id' (default), 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + assetsSort: "field", + + // Add build date and time information + builtAt: true, + + // Add information about cached (not built) modules + cached: true, + + // Show cached assets (setting this to `false` only shows emitted files) + cachedAssets: true, + + // Add children information + children: true, + + // Add chunk information (setting this to `false` allows for a less verbose output) + chunks: true, + + // Add namedChunkGroups information + chunkGroups: true, + + // Add built modules information to chunk information + chunkModules: true, + + // Add the origins of chunks and chunk merging info + chunkOrigins: true, + + // Sort the chunks by a field + // You can reverse the sort with `!field`. Default is `id`. + // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + chunksSort: "field", + + // Context directory for request shortening + context: "../src/", + + // `webpack --colors` equivalent + colors: false, + + // Display the distance from the entry point for each module + depth: false, + + // Display the entry points with the corresponding bundles + entrypoints: false, + + // Add --env information + env: false, + + // Add errors + errors: true, + + // Add details to errors (like resolving log) + errorDetails: true, + + // Exclude assets from being displayed in stats + // This can be done with a String, a RegExp, a Function getting the assets name + // and returning a boolean or an Array of the above. + excludeAssets: "filter" | /filter/ | (assetName) => true | false | + ["filter"] | [/filter/] | [(assetName) => true|false], + + // Exclude modules from being displayed in stats + // This can be done with a String, a RegExp, a Function getting the modules source + // and returning a boolean or an Array of the above. + excludeModules: "filter" | /filter/ | (moduleSource) => true | false | + ["filter"] | [/filter/] | [(moduleSource) => true|false], + + // See excludeModules + exclude: "filter" | /filter/ | (moduleSource) => true | false | + ["filter"] | [/filter/] | [(moduleSource) => true|false], + + // Add the hash of the compilation + hash: true, + + // Set the maximum number of modules to be shown + maxModules: 15, + + // Add built modules information + modules: true, + + // Sort the modules by a field + // You can reverse the sort with `!field`. Default is `id`. + // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' + // For a complete list of fields see the bottom of the page + modulesSort: "field", + + // Show dependencies and origin of warnings/errors (since webpack 2.5.0) + moduleTrace: true, + + // Show performance hint when file size exceeds `performance.maxAssetSize` + performance: true, + + // Show the exports of the modules + providedExports: false, + + // Add public path information + publicPath: true, + + // Add information about the reasons why modules are included + reasons: true, + + // Add the source code of modules + source: false, + + // Add timing information + timings: true, + + // Show which exports of a module are used + usedExports: false, + + // Add webpack version information + version: true, + + // Add warnings + warnings: true, + + // Filter warnings to be shown (since webpack 2.4.0), + // can be a String, Regexp, a function getting the warning and returning a boolean + // or an Array of a combination of the above. First match wins. + warningsFilter: "filter" | /filter/ | ["filter", /filter/] | (warning) => true|false + } +} +``` + +If you want to use one of the pre-defined behaviours e.g. `'minimal'` but still override one or more of the rules, see [the source code](https://github.com/webpack/webpack/blob/master/lib/Stats.js#L1394-L1401). You would want to copy the configuration options from `case 'minimal': ...` and add your additional rules while providing an object to `stats`. + +__webpack.config.js__ + +```javascript +module.exports = { + //.. + stats: { + // copied from `'minimal'` + all: false, + modules: true, + maxModules: 0, + errors: true, + warnings: true, + // our additional options + moduleTrace: true, + errorDetails: true + } +}; +``` + +### Sorting fields + +For `assetsSort`, `chunksSort` and `moduleSort` there are several possible fields that you can sort items by: + +- `id` is the item's id; +- `name` - a item's name that was assigned to it upon importing; +- `size` - a size of item in bytes; +- `chunks` - what chunks the item originates from (for example, if there are multiple subchunks for one chunk - the subchunks will be grouped together according to their main chunk); +- `errors` - amount of errors in items; +- `warnings` - amount of warnings in items; +- `failed` - whether the item has failed compilation; +- `cacheable` - whether the item is cacheable; +- `built` - whether the asset has been built; +- `prefetched` - whether the asset will be prefetched; +- `optional` - whether the asset is optional; +- `identifier` - identifier of the item; +- `index` - item's processing index; +- `index2` +- `profile` +- `issuer` - an identifier of the issuer; +- `issuerId` - an id of the issuer; +- `issuerName` - a name of the issuer; +- `issuerPath` - a full issuer object. There's no real need to sort by this field; + + +# Other Options + + +These are the remaining configuration options supported by webpack. + +W> Help Wanted: This page is still a work in progress. If you are familiar with any of the options for which the description or examples are incomplete, please create an issue and submit a PR at the [docs repo](https://github.com/webpack/webpack.js.org)! + + +## `amd` + +`object` + +Set the value of `require.amd` or `define.amd`: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + amd: { + jQuery: true + } +}; +``` + +Certain popular modules written for AMD, most notably jQuery versions 1.7.0 to 1.9.1, will only register as an AMD module if the loader indicates it has taken [special allowances](https://github.com/amdjs/amdjs-api/wiki/jQuery-and-AMD) for multiple versions being included on a page. + +The allowances were the ability to restrict registrations to a specific version or to support different sandboxes with different defined modules. + +This option allows you to set the key your module looks for to a truthy value. +As it happens, the AMD support in webpack ignores the defined name anyways. + + +## `bail` + +`boolean` + +Fail out on the first error instead of tolerating it. By default webpack will log these errors in red in the terminal, as well as the browser console when using HMR, but continue bundling. To enable it: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + bail: true +}; +``` + +This will force webpack to exit its bundling process. + + +## `cache` + +`boolean` `object` + +Cache the generated webpack modules and chunks to improve build speed. Caching is enabled by default while in watch mode. To disable caching simply pass: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + cache: false +}; +``` + +If an object is passed, webpack will use this object for caching. Keeping a reference to this object will allow one to share the same cache between compiler calls: + +__webpack.config.js__ + +```javascript +let SharedCache = {}; + +module.exports = { + //... + cache: SharedCache +}; +``` + +W> Don't share the cache between calls with different options. + +?> Elaborate on the warning and example - calls with different configuration options? + + +## `loader` + +`object` + +Expose custom values into the loader context. + +?> Add an example... + + +## `parallelism` + +`number` + +Limit the number of parallel processed modules. Can be used to fine tune performance or to get more reliable profiling results. + + +## `profile` + +`boolean` + +Capture a "profile" of the application, including statistics and hints, which can then be dissected using the [Analyze](https://webpack.github.io/analyse/) tool. + +T> Use the [StatsPlugin](https://www.npmjs.com/package/stats-webpack-plugin) for more control over the generated profile. + +T> Combine with `parallelism: 1` for better results. + + +## `recordsPath` + +`string` + +Use this option to generate a JSON file containing webpack "records" -- pieces of data used to store module identifiers across multiple builds. You can use this file to track how modules change between builds. To generate one, simply specify a location: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + recordsPath: path.join(__dirname, 'records.json') +}; +``` + +Records are particularly useful if you have a complex setup that leverages [Code Splitting](/guides/code-splitting). The data can be used to ensure the split bundles are achieving the [caching](/guides/caching) behavior you need. + +T> Note that although this file is generated by the compiler, you may still want to track it in source control to keep a history of how it has changed over time. + +W> Setting `recordsPath` will essentially set `recordsInputPath` and `recordsOutputPath` to the same location. This is usually all that's necessary unless you decide to change the name of the file containing the records. See below for an example. + + +## `recordsInputPath` + +`string` + +Specify the file from which to read the last set of records. This can be used to rename a records file. See the example below. + + +## `recordsOutputPath` + +`string` + +Specify where the records should be written. The following example shows how you might use this option in combination with `recordsInputPath` to rename a records file: + +__webpack.config.js__ + +```javascript +module.exports = { + //... + recordsInputPath: path.join(__dirname, 'records.json'), + recordsOutputPath: path.join(__dirname, 'newRecords.json') +}; +``` + + +## `name` + +`string` + +Name of the configuration. Used when loading multiple configurations. + +__webpack.config.js__ + +```javascript +module.exports = { + //... + name: 'admin-app' +}; +``` diff --git a/src/content/contribute/_contribute_all.md b/src/content/contribute/_contribute_all.md new file mode 100644 index 000000000000..beab316a12a7 --- /dev/null +++ b/src/content/contribute/_contribute_all.md @@ -0,0 +1,979 @@ + + +# Contribute + +The people who contribute to webpack do so for the love of open source, our users and ecosystem, and most importantly, pushing the web forward together. Because of our [Open Collective](https://opencollective.com/webpack) model for funding and transparency, we are able to funnel support and funds through contributors, dependent projects, and the contributor and core teams. To make a donation, simply click the button below... + +<div align="center"> + <a href="https://opencollective.com/webpack/donate" target="_blank"> + <img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" width=300 /> + </a> +</div> + +But what is the return on the investment? + + +## Developers + +The biggest core feature we'd like to provide is enjoyable development experience. Developers like you can help by contributing to rich and vibrant documentation, issuing pull requests to help us cover niche use cases, and to help sustain what you love about webpack. + +### How Can I Help? + +Anybody can help by doing any of the following: + +- Ask your employer to use webpack in projects. +- Help us write and maintain the content on this site (see the [writer's guide](/writers-guide)). +- Contribute to the [core repository](https://github.com/webpack/webpack). +- Become a backer or sponsor on [open collective](https://opencollective.com/webpack#support). + +### Encouraging Employers + +You can ask your employer to improve your workflow by leveraging webpack: an all-in-one tool for fonts, images and image optimization, and json. Explain to them how webpack will attempt to bundle your code and assets the best it can for the smallest file size, leading to speedier sites and applications. + +### Your Contributions + +Contributing to webpack is not contributing to an exclusive club. You as a developer are contributing to the overall health of downstream projects. Hundreds, if not thousands, of projects depend on webpack and contributing will make the ecosystem better for all users. + +The remainder of this section of the site is dedicated to developers such as yourself who would like to become a part of our ever-growing community: + +- [Writing a Loader](./writing-a-loader) +- [Writing a Plugin](./writing-a-plugin) +- [Plugin Patterns](./plugin-patterns) +- [Release Process](./release-process) + + +## Executives + +CTO's, VPs, and owners can help too! + +<!-- add slides here regarding monetary value/dev time/tooling --> + +webpack is an all-in-one tool for bundling your code. It can handle fonts, images, data and more with the help of community-driven plugins and loaders. Having all of your assets be handled by one tool is immensely helpful, as you or your team can spend less time making sure a machine with many moving parts is working correctly and more time building your product. + +### Sponsorship + +Aside from monetary assistance, companies can support webpack by: + +- Providing developers that are not actively working on a project. +- Contributing computing power for improved CI and regression testing. + +You can also encourage your developers to contribute to the ecosystem by open-sourcing webpack loaders, plugins and other utilities. And, as mentioned above, we would greatly appreciate any help increasing our CI/CD infrastructure. + +### Anyone Else + +To anyone else who is interested in helping our mission -- e.g. venture capitalists, government entities, digital agencies, etc. -- we would love for you to work with us, one of the top npm packages, to improve your product! Please don't hesitate to reach out with questions. + +<!-- add slides here --> + + +# Writer's Guide + +The following sections contain all you need to know about editing and formatting the content within this site. Make sure to do some research before starting your edits or additions. Sometimes the toughest part is finding where the content should live and determining whether or not it already exists. + + +## Process + +1. Check related issue if an article links to one. +2. Hit `edit` and expand on the structure. +3. PR changes. + + +## YAML Frontmatter + +Each article contains a small section at the top written in [YAML Frontmatter](https://jekyllrb.com/docs/frontmatter/): + +``` yaml +--- +title: My Article +group: My Sub-Section +sort: 3 +contributors: + - [github username] +related: + - title: Title of Related Article + url: [url of related article] +--- +``` + +Let's break these down: + +- `title`: The name of the article. +- `group`: The name of the sub-section +- `sort`: The order of the article within its section (or) sub-section if it is present. +- `contributors`: A list of GitHub usernames who have contributed to this article. +- `related`: Any related reading or useful examples. + +Note that `related` will generate a __Further Reading__ section at the bottom of the page and `contributors` will yield a __Contributors__ section below it. If you edit an article and would like recognition, don't hesitate to add your GitHub username to the `contributors` list. + + +## Article Structure + +1. Brief Introduction - a paragraph or two so you get the basic idea about the what and why. +2. Outline Remaining Content – how the content will be presented. +3. Main Content - tell what you promised to tell. +4. Conclusion - tell what you told and recap the main points. + + +## Typesetting + +- webpack should always be written in lower-case letters. Even at the beginning of a sentence. ([source](https://github.com/webpack/media#name)) +- loaders are enclosed in backticks and [kebab-cased](https://en.wikipedia.org/w/index.php?title=Kebab_case): `css-loader`, `ts-loader`, … +- plugins are enclosed in backticks and [camel-cased](https://en.wikipedia.org/wiki/Camel_case): `BannerPlugin`, `NpmInstallWebpackPlugin`, … +- Use "webpack 2" to refer to a specific webpack version (~~"webpack v2"~~) +- Use ES5; ES2015, ES2016, … to refer to the ECMAScript standards (~~ES6~~, ~~ES7~~) + + +## Formatting + +### Code + +__Syntax: \`\`\`javascript … \`\`\`__ + +```javascript +function foo () { + return 'bar'; +} + +foo(); +``` + +### Lists + +- Boo +- Foo +- Zoo + +Lists should be ordered alphabetically. + +### Tables + +Parameter | Explanation | Input Type | Default Value +----------- | ------------------------------------------------ | ---------- |-------------- +--debug | Switch loaders to debug mode | boolean | false +--devtool | Define source map type for the bundled resources | string | - +--progress | Print compilation progress in percentage | boolean | false + +Tables should also be ordered alphabetically. + +### Configuration Properties + +The [configuration](/configuration) properties should be ordered alphabetically as well: + +- `devServer.compress` +- `devServer.contentBase` +- `devServer.hot` + +### Quotes + +#### Blockquote + +__Syntax: \>__ + +> This is a blockquote. + +#### Tip + +__Syntax: T\>__ + +T> This is a tip. + +__Syntax: W\>__ + +W> This is a warning. + +__Syntax: ?\>__ + +?> This is a todo. + + +# Writing a Loader + +A loader is a node module that exports a function. This function is called when a resource should be transformed by this loader. The given function will have access to the [Loader API](/api/loaders/) using the `this` context provided to it. + + +## Setup + +Before we dig into the different types of loaders, their usage, and examples, let's take a look at the three ways you can develop and test a loader locally. + +To test a single loader, you can simply use `path` to `resolve` a local file within a rule object: + +__webpack.config.js__ + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + use: [ + { + loader: path.resolve('path/to/loader.js'), + options: {/* ... */} + } + ] + } + ] + } +}; +``` + +To test multiple, you can utilize the `resolveLoader.modules` configuration to update where webpack will search for loaders. For example, if you had a local `/loaders` directory in your project: + +__webpack.config.js__ + +```js +module.exports = { + //... + resolveLoader: { + modules: [ + 'node_modules', + path.resolve(__dirname, 'loaders') + ] + } +}; +``` + +Last but not least, if you've already created a separate repository and package for your loader, you could [`npm link`](https://docs.npmjs.com/cli/link) it to the project in which you'd like to test it out. + + +## Simple Usage + +When a single loader is applied to the resource, the loader is called with only one parameter -- a string containing the content of the resource file. + +Synchronous loaders can simply `return` a single value representing the transformed module. In more complex cases, the loader can return any number of values by using the `this.callback(err, values...)` function. Errors are either passed to the `this.callback` function or thrown in a sync loader. + +The loader is expected to give back one or two values. The first value is a resulting JavaScript code as string or buffer. The second optional value is a SourceMap as JavaScript object. + + +## Complex Usage + +When multiple loaders are chained, it is important to remember that they are executed in reverse order -- either right to left or bottom to top depending on array format. + +- The last loader, called first, will be passed the contents of the raw resource. +- The first loader, called last, is expected to return JavaScript and an optional source map. +- The loaders in between will be executed with the result(s) of the previous loader in the chain. + +So, in the following example, the `foo-loader` would be passed the raw resource and the `bar-loader` would receive the output of the `foo-loader` and return the final transformed module and a source map if necessary. + +__webpack.config.js__ + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js/, + use: [ + 'bar-loader', + 'foo-loader' + ] + } + ] + } +}; +``` + + +## Guidelines + +The following guidelines should be followed when writing a loader. They are ordered in terms of importance and some only apply in certain scenarios, read the detailed sections that follow for more information. + +- Keep them __simple__. +- Utilize __chaining__. +- Emit __modular__ output. +- Make sure they're __stateless__. +- Employ __loader utilities__. +- Mark __loader dependencies__. +- Resolve __module dependencies__. +- Extract __common code__. +- Avoid __absolute paths__. +- Use __peer dependencies__. + +### Simple + +Loaders should do only a single task. This not only makes the job of maintaining each loader easier, but also allows them to be chained for usage in more scenarios. + +### Chaining + +Take advantage of the fact that loaders can be chained together. Instead of writing a single loader that tackles five tasks, write five simpler loaders that divide this effort. Isolating them not only keeps each individual loader simple, but may allow for them to be used for something you hadn't thought of originally. + +Take the case of rendering a template file with data specified via loader options or query parameters. It could be written as a single loader that compiles the template from source, executes it and returns a module that exports a string containing the HTML code. However, in accordance with guidelines, a simple `apply-loader` exists that can be chained with other open source loaders: + +- `jade-loader`: Convert template to a module that exports a function. +- `apply-loader`: Executes the function with loader options and returns raw HTML. +- `html-loader`: Accepts HTML and outputs a valid JavaScript module. + +T> The fact that loaders can be chained also means they don't necessarily have to output JavaScript. As long as the next loader in the chain can handle its output, the loader can return any type of module. + +### Modular + +Keep the output modular. Loader generated modules should respect the same design principles as normal modules. + +### Stateless + +Make sure the loader does not retain state between module transformations. Each run should always be independent of other compiled modules as well as previous compilations of the same module. + +### Loader Utilities + +Take advantage of the [`loader-utils`](https://github.com/webpack/loader-utils) package. It provides a variety of useful tools but one of the most common is retrieving the options passed to the loader. Along with `loader-utils`, the [`schema-utils`](https://github.com/webpack-contrib/schema-utils) package should be used for consistent JSON Schema based validation of loader options. Here's a brief example that utilizes both: + +__loader.js__ + +```js +import { getOptions } from 'loader-utils'; +import validateOptions from 'schema-utils'; + +const schema = { + type: 'object', + properties: { + test: { + type: 'string' + } + } +}; + +export default function(source) { + const options = getOptions(this); + + validateOptions(schema, options, 'Example Loader'); + + // Apply some transformations to the source... + + return `export default ${ JSON.stringify(source) }`; +} +``` + +### Loader Dependencies + +If a loader uses external resources (i.e. by reading from filesystem), they __must__ indicate it. This information is used to invalidate cacheable loaders and recompile in watch mode. Here's a brief example of how to accomplish this using the `addDependency` method: + +__loader.js__ + +```js +import path from 'path'; + +export default function(source) { + var callback = this.async(); + var headerPath = path.resolve('header.js'); + + this.addDependency(headerPath); + + fs.readFile(headerPath, 'utf-8', function(err, header) { + if(err) return callback(err); + callback(null, header + '\n' + source); + }); +} +``` + +### Module Dependencies + +Depending on the type of module, there may be a different schema used to specify dependencies. In CSS for example, the `@import` and `url(...)` statements are used. These dependencies should be resolved by the module system. + +This can be done in one of two ways: + +- By transforming them to `require` statements. +- Using the `this.resolve` function to resolve the path. + +The `css-loader` is a good example of the first approach. It transforms dependencies to `require`s, by replacing `@import` statements with a `require` to the other stylesheet and `url(...)` with a `require` to the referenced file. + +In the case of the `less-loader`, it cannot transform each `@import` to a `require` because all `.less` files must be compiled in one pass for variables and mixin tracking. Therefore, the `less-loader` extends the less compiler with custom path resolving logic. It then takes advantage of the second approach, `this.resolve`, to resolve the dependency through webpack. + +T> If the language only accepts relative urls (e.g. `url(file)` always refers to `./file`), you can use the `~` convention to specify references to installed modules (e.g. those in `node_modules`). So, in the case of `url`, that would look something like `url('~some-library/image.jpg')`. + +### Common Code + +Avoid generating common code in every module the loader processes. Instead, create a runtime file in the loader and generate a `require` to that shared module. + +### Absolute Paths + +Don't insert absolute paths into the module code as they break hashing when the root for the project is moved. There's a [`stringifyRequest`](https://github.com/webpack/loader-utils#stringifyrequest) method in `loader-utils` which can be used to convert an absolute path to a relative one. + +### Peer Dependencies + +If the loader you're working on is a simple wrapper around another package, then you should include the package as a `peerDependency`. This approach allows the application's developer to specify the exact version in the `package.json` if desired. + +For instance, the `sass-loader` [specifies `node-sass`](https://github.com/webpack-contrib/sass-loader/blob/master/package.json) as peer dependency like so: + +```json +{ + "peerDependencies": { + "node-sass": "^4.0.0" + } +} +``` + + +## Testing + +So you've written a loader, followed the guidelines above, and have it set up to run locally. What's next? Let's go through a simple unit testing example to ensure our loader is working the way we expect. We'll be using the [Jest](https://facebook.github.io/jest/) framework to do this. We'll also install `babel-jest` and some presets that will allow us to use the `import` / `export` and `async` / `await`. Let's start by installing and saving these as a `devDependencies`: + +``` bash +npm install --save-dev jest babel-jest babel-preset-env +``` + +__.babelrc__ + +```json +{ + "presets": [[ + "env", + { + "targets": { + "node": "4" + } + } + ]] +} +``` + +Our loader will process `.txt` files and simply replace any instance of `[name]` with the `name` option given to the loader. Then it will output a valid JavaScript module containing the text as it's default export: + +__src/loader.js__ + +```js +import { getOptions } from 'loader-utils'; + +export default function loader(source) { + const options = getOptions(this); + + source = source.replace(/\[name\]/g, options.name); + + return `export default ${ JSON.stringify(source) }`; +} +``` + +We'll use this loader to process the following file: + +__test/example.txt__ + +``` text +Hey [name]! +``` + +Pay close attention to this next step as we'll be using the [Node.js API](/api/node) and [`memory-fs`](https://github.com/webpack/memory-fs) to execute webpack. This lets us avoid emitting `output` to disk and will give us access to the `stats` data which we can use to grab our transformed module: + +``` bash +npm install --save-dev webpack memory-fs +``` + +__test/compiler.js__ + +```js +import path from 'path'; +import webpack from 'webpack'; +import memoryfs from 'memory-fs'; + +export default (fixture, options = {}) => { + const compiler = webpack({ + context: __dirname, + entry: `./${fixture}`, + output: { + path: path.resolve(__dirname), + filename: 'bundle.js', + }, + module: { + rules: [{ + test: /\.txt$/, + use: { + loader: path.resolve(__dirname, '../src/loader.js'), + options: { + name: 'Alice' + } + } + }] + } + }); + + compiler.outputFileSystem = new memoryfs(); + + return new Promise((resolve, reject) => { + compiler.run((err, stats) => { + if (err || stats.hasErrors()) reject(err); + + resolve(stats); + }); + }); +}; +``` + +T> In this case, we've inlined our webpack configuration but you can also accept a configuration as a parameter to the exported function. This would allow you to test multiple setups using the same compiler module. + +And now, finally, we can write our test and add an npm script to run it: + +__test/loader.test.js__ + +```js +import compiler from './compiler.js'; + +test('Inserts name and outputs JavaScript', async () => { + const stats = await compiler('example.txt'); + const output = stats.toJson().modules[0].source; + + expect(output).toBe('export default "Hey Alice!\\n"'); +}); +``` + +__package.json__ + +```json +{ + "scripts": { + "test": "jest" + } +} +``` + +With everything in place, we can run it and see if our new loader passes the test: + +``` bash + PASS test/loader.test.js + ✓ Inserts name and outputs JavaScript (229ms) + +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: 1.853s, estimated 2s +Ran all test suites. +``` + +It worked! At this point you should be ready to start developing, testing, and deploying your own loaders. We hope that you'll share your creations with the rest of the community! + + +# Writing a Plugin + +Plugins expose the full potential of the webpack engine to third-party developers. Using staged build callbacks, developers can introduce their own behaviors into the webpack build process. Building plugins is a bit more advanced than building loaders, because you'll need to understand some of the webpack low-level internals to hook into them. Be prepared to read some source code! + +## Creating a Plugin + +A plugin for webpack consists of + +- A named JavaScript function. +- Defines `apply` method in its prototype. +- Specifies an [event hook](/api/compiler-hooks/) to tap into. +- Manipulates webpack internal instance specific data. +- Invokes webpack provided callback after functionality is complete. + +```javascript +// A JavaScript class. +class MyExampleWebpackPlugin { + // Define `apply` as its prototype method which is supplied with compiler as its argument + apply(compiler) { + // Specify the event hook to attach to + compiler.hooks.emit.tapAsync( + 'MyExampleWebpackPlugin', + (compilation, callback) => { + console.log('This is an example plugin!'); + console.log('Here’s the `compilation` object which represents a single build of assets:', compilation); + + // Manipulate the build using the plugin API provided by webpack + compilation.addModule(/* ... */); + + callback(); + } + ); + } +} +``` + +## Basic plugin architecture + +Plugins are instantiated objects with an `apply` method on their prototype. This `apply` method is called once by the webpack compiler while installing the plugin. The `apply` method is given a reference to the underlying webpack compiler, which grants access to compiler callbacks. A simple plugin is structured as follows: + +```javascript +class HelloWorldPlugin { + apply(compiler) { + compiler.hooks.done.tap('Hello World Plugin', ( + stats /* stats is passed as argument when done hook is tapped. */ + ) => { + console.log('Hello World!'); + }); + } +} + +module.exports = HelloWorldPlugin; +``` + +Then to use the plugin, include an instance in your webpack config `plugins` array: + +```javascript +// webpack.config.js +var HelloWorldPlugin = require('hello-world'); + +module.exports = { + // ... config settings here ... + plugins: [new HelloWorldPlugin({ options: true })] +}; +``` + +## Compiler and Compilation + +Among the two most important resources while developing plugins are the `compiler` and `compilation` objects. Understanding their roles is an important first step in extending the webpack engine. + +```javascript +class HelloCompilationPlugin { + apply(compiler) { + // Tap into compilation hook which gives compilation as argument to the callback function + compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => { + // Now we can tap into various hooks available through compilation + compilation.hooks.optimize.tap('HelloCompilationPlugin', () => { + console.log('Assets are being optimized.'); + }); + }); + } +} + +module.exports = HelloCompilationPlugin; +``` + +The list of hooks available on the `compiler`, `compilation`, and other important objects, see the [plugins API](/api/plugins/) docs. + +## Async event hooks + +Some plugin hooks are asynchronous. To tap into them, we can use `tap` method which will behave in synchronous manner or use one of `tapAsync` method or `tapPromise` method which are asynchronous methods. + +### tapAsync + +When we use `tapAsync` method to tap into plugins, we need to call the callback function which is supplied as the last argument to our function. + +```javascript +class HelloAsyncPlugin { + apply(compiler) { + compiler.hooks.emit.tapAsync('HelloAsyncPlugin', (compilation, callback) => { + // Do something async... + setTimeout(function() { + console.log('Done with async work...'); + callback(); + }, 1000); + }); + } +} + +module.exports = HelloAsyncPlugin; +``` + +#### tapPromise + +When we use `tapPromise` method to tap into plugins, we need to return a promise which resolves when our asynchronous task is completed. + +```javascript +class HelloAsyncPlugin { + apply(compiler) { + compiler.hooks.emit.tapPromise('HelloAsyncPlugin', compilation => { + // return a Promise that resolves when we are done... + return new Promise((resolve, reject) => { + setTimeout(function() { + console.log('Done with async work...'); + resolve(); + }, 1000); + }); + }); + } +} + +module.exports = HelloAsyncPlugin; +``` + +## Example + +Once we can latch onto the webpack compiler and each individual compilations, the possibilities become endless for what we can do with the engine itself. We can reformat existing files, create derivative files, or fabricate entirely new assets. + +Let's write a simple example plugin that generates a new build file called `filelist.md`; the contents of which will list all of the asset files in our build. This plugin might look something like this: + +```javascript +class FileListPlugin { + apply(compiler) { + // emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well + compiler.hooks.emit.tapAsync('FileListPlugin', (compilation, callback) => { + // Create a header string for the generated file: + var filelist = 'In this build:\n\n'; + + // Loop through all compiled assets, + // adding a new line item for each filename. + for (var filename in compilation.assets) { + filelist += '- ' + filename + '\n'; + } + + // Insert this list into the webpack build as a new file asset: + compilation.assets['filelist.md'] = { + source: function() { + return filelist; + }, + size: function() { + return filelist.length; + } + }; + + callback(); + }); + } +} + +module.exports = FileListPlugin; +``` + +## Different Plugin Shapes + +A plugin can be classified into types based on the event hooks it taps into. Every event hook is pre-defined as synchronous or asynchronous or waterfall or parallel hook and hook is called internally using call/callAsync method. The list of hooks that are supported or can be tapped into are generally specified in this.hooks property. + +For example:- + +```javascript +this.hooks = { + shouldEmit: new SyncBailHook(['compilation']) +}; +``` + +It represents that the only hook supported is `shouldEmit` which is a hook of `SyncBailHook` type and the only parameter which will be passed to any plugin that taps into `shouldEmit` hook is `compilation`. + +Various types of hooks supported are :- + +### Synchronous Hooks + +- __SyncHook__ + + - Defined as `new SyncHook([params])` + - Tapped into using `tap` method. + - Called using `call(...params)` method. + +- __Bail Hooks__ + + - Defined using `SyncBailHook[params]` + - Tapped into using `tap` method. + - Called using `call(...params)` method. + + In these type of hooks, each of the plugin callbacks will be invoked one after the other with the specific `args`. If any value is returned except undefined by any plugin, then that value is returned by hook and no further plugin callback is invoked. Many useful events like `optimizeChunks`, `optimizeChunkModules` are SyncBailHooks. + +- __Waterfall Hooks__ + + - Defined using `SyncWaterfallHook[params]` + - Tapped into using `tap` method. + - Called using `call( ... params)` method + + Here each of the plugins are called one after the other with the arguments from the return value of the previous plugin. The plugin must take the order of its execution into account. + It must accept arguments from the previous plugin that was executed. The value for the first plugin is `init`. Hence at least 1 param must be supplied for waterfall hooks. This pattern is used in the Tapable instances which are related to the webpack templates like `ModuleTemplate`, `ChunkTemplate` etc. + +### Asynchronous Hooks + +- __Async Series Hook__ + + - Defined using `AsyncSeriesHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + The plugin handler functions are called with all arguments and a callback function with the signature `(err?: Error) -> void`. The handler functions are called in order of registration. `callback` is called after all the handlers are called. + This is also a commonly used pattern for events like `emit`, `run`. + +- __Async waterfall__ The plugins will be applied asynchronously in the waterfall manner. + + - Defined using `AsyncWaterfallHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + The plugin handler functions are called with the current value and a callback function with the signature `(err: Error, nextValue: any) -> void.` When called `nextValue` is the current value for the next handler. The current value for the first handler is `init`. After all handlers are applied, callback is called with the last value. If any handler passes a value for `err`, the callback is called with this error and no more handlers are called. + This plugin pattern is expected for events like `before-resolve` and `after-resolve`. + +- __Async Series Bail__ + + - Defined using `AsyncSeriesBailHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + someMethod() { + // Call a hook: + this.hooks.compilation.call(); + +- __Async Parallel__ + + - Defined using `AsyncParallelHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + +- __Async Series Bail__ + + - Defined using `AsyncSeriesBailHook[params]` + - Tapped into using `tap`/`tapAsync`/`tapPromise` method. + - Called using `callAsync( ... params)` method + + +# Plugin Patterns + +Plugins grant unlimited opportunity to perform customizations within the webpack build system. This allows you to create custom asset types, perform unique build modifications, or even enhance the webpack runtime while using middleware. The following are some features of webpack that become useful while writing plugins. + +## Exploring assets, chunks, modules, and dependencies + +After a compilation is sealed, all structures within the compilation may be traversed. + +```javascript +class MyPlugin { + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + // Explore each chunk (build output): + compilation.chunks.forEach(chunk => { + // Explore each module within the chunk (built inputs): + chunk.modules.forEach(module => { + // Explore each source file path that was included into the module: + module.fileDependencies.forEach(filepath => { + // we've learned a lot about the source structure now... + }); + }); + + // Explore each asset filename generated by the chunk: + chunk.files.forEach(filename => { + // Get the asset source for each file generated by the chunk: + var source = compilation.assets[filename].source(); + }); + }); + + callback(); + }); + } +} +module.exports = MyPlugin; +``` + +- `compilation.modules`: An array of modules (built inputs) in the compilation. Each module manages the build of a raw file from your source library. +- `module.fileDependencies`: An array of source file paths included into a module. This includes the source JavaScript file itself (ex: `index.js`), and all dependency asset files (stylesheets, images, etc) that it has required. Reviewing dependencies is useful for seeing what source files belong to a module. +- `compilation.chunks`: An array of chunks (build outputs) in the compilation. Each chunk manages the composition of a final rendered assets. +- `chunk.modules`: An array of modules that are included into a chunk. By extension, you may look through each module's dependencies to see what raw source files fed into a chunk. +- `chunk.files`: An array of output filenames generated by the chunk. You may access these asset sources from the `compilation.assets` table. + +### Monitoring the watch graph + +While running webpack middleware, each compilation includes a `fileDependencies` array (what files are being watched) and a `fileTimestamps` hash that maps watched file paths to a timestamp. These are extremely useful for detecting what files have changed within the compilation: + +```javascript +class MyPlugin { + constructor() { + this.startTime = Date.now(); + this.prevTimestamps = {}; + } + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + var changedFiles = Object.keys(compilation.fileTimestamps).filter( + watchfile => { + return ( + (this.prevTimestamps[watchfile] || this.startTime) < + (compilation.fileTimestamps[watchfile] || Infinity) + ); + } + ); + + this.prevTimestamps = compilation.fileTimestamps; + callback(); + }); + } +} + +module.exports = MyPlugin; +``` + +You may also feed new file paths into the watch graph to receive compilation triggers when those files change. Simply push valid file paths into the `compilation.fileDependencies` array to add them to the watch. Note: the `fileDependencies` array is rebuilt in each compilation, so your plugin must push its own watched dependencies into each compilation to keep them under watch. + +## Changed chunks + +Similar to the watch graph, it's fairly simple to monitor changed chunks (or modules, for that matter) within a compilation by tracking their hashes. + +```javascript +class MyPlugin { + constructor() { + this.chunkVersions = {}; + } + apply(compiler) { + compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { + var changedChunks = compilation.chunks.filter(chunk => { + var oldVersion = this.chunkVersions[chunk.name]; + this.chunkVersions[chunk.name] = chunk.hash; + return chunk.hash !== oldVersion; + }); + callback(); + }); + } +} + +module.exports = MyPlugin; +``` + + +# Release Process + +The release process for deploying webpack is actually quite painless. Read through the following steps, so you have a clear understanding of how it's done. + + +## Pull Requests + +When merging pull requests into the `master` branch, select the _Create Merge Commit_ option. + + +## Releasing + +```sh +npm version patch && git push --follow-tags && npm publish +npm version minor && git push --follow-tags && npm publish +npm version major && git push --follow-tags && npm publish +``` + +_This will increment the package version, commits the changes, cuts a __local tag__, push to github & publish the npm package._ + +After that go to the github [releases page](https://github.com/webpack/webpack/releases) and write a Changelog for the new tag. + + +# Debugging + +When contributing to the core repo, writing a loader/plugin, or even just working on complex project, debugging tools can be central to your workflow. Whether the problem is slow performance on a large project or an unhelpful traceback, the following utilities can make figuring it out less painful. + +- The [`stats` data](/api/stats) made available through [Node](/api/node#stats-object) and the [CLI](/api/cli#common-options). +- Chrome __DevTools__ via `node-nightly` and the latest Node.js versions. + + +## Stats + +Whether you want to sift through [this data](/api/stats) manually or use a tool to process it, the `stats` data can be extremely useful when debugging build issues. We won't go in depth here as there's an [entire page](/api/stats) dedicated to its contents, but know that you can use it to find the following information: + +- The contents of every module. +- The modules contained within every chunk. +- Per module compilation and resolving stats. +- Build errors and warnings. +- The relationships between modules. +- And much more... + +On top of that, the official [analyze tool](https://github.com/webpack/analyse) and [various others](/guides/code-splitting#bundle-analysis) will accept this data and visualize it in various ways. + + +## DevTools + +While [`console`](https://nodejs.org/api/console.html) statements may work well in simpler scenarios, sometimes a more robust solution is needed. As most front-end developers already know, Chrome DevTools are a life saver when debugging web applications, _but they don’t have to stop there_. As of Node v6.3.0+, developers can use the built-in `--inspect` flag to debug a node program in DevTools. + +This gives you the power to easily create breakpoints, debug memory usage, expose and examine objects in the console, and much more. In this short demo, we'll utilize the [`node-nightly`](https://github.com/hemanth/node-nightly) package which provides access to the latest and greatest inspecting capabilities. + +W> The `--inspect` interface has been available since v6.3.0 so feel to try it out with your local version, but be warned that certain features and flags may differ from the ones in this demo. + +Let's start by installing it globally: + +``` bash +npm install --global node-nightly +``` + +Now, we'll need to run it once to finish the installation: + +``` bash +node-nightly +``` + +Now, we can simply use `node-nightly` along with the `--inspect` flag to start our build in any webpack-based project. Note that we cannot run NPM `scripts`, e.g. `npm run build`, so we'll have specify the full `node_modules` path: + +``` bash +node-nightly --inspect ./node_modules/webpack/bin/webpack.js +``` + +Which should output something like: + +``` bash +Debugger listening on ws://127.0.0.1:9229/c624201a-250f-416e-a018-300bbec7be2c +For help see https://nodejs.org/en/docs/inspector +``` + +Now jump to `chrome://inspect` in the browser and you should see any active scripts you've inspected under the _Remote Target_ header. Click the "inspect" link under each script to open a dedicated debugger or the _Open dedicated DevTools for Node_ link for a session that will connect automatically. You can also check out the [NiM extension](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj), a handy Chrome plugin that will automatically open a DevTools tab every time you `--inspect` a script. + +We recommend using the `--inspect-brk` flag which will break on the first statement of the script allowing you to go through the source to set breakpoints and start/stop the build as you please. Also, don't forget that you can still pass arguments to the script. For example, if you have multiple configuration files you could pass `--config webpack.prod.js` to specify the configuration you'd like to debug. diff --git a/src/content/guides/_guides_all.md b/src/content/guides/_guides_all.md new file mode 100644 index 000000000000..dab542340ea2 --- /dev/null +++ b/src/content/guides/_guides_all.md @@ -0,0 +1,4880 @@ + + +# Installation + +This guide goes through the various methods used to install webpack. + + +## Prerequisites + +Before we begin, make sure you have a fresh version of [Node.js](https://nodejs.org/en/) installed. The current Long Term Support (LTS) release is an ideal starting point. You may run into a variety of issues with the older versions as they may be missing functionality webpack and/or its related packages require. + + +## Local Installation + +The latest webpack release is: + +[](https://github.com/webpack/webpack/releases) + +To install the latest release or a specific version, run one of the following commands: + +``` bash +npm install --save-dev webpack +npm install --save-dev webpack@<version> +``` + +If you're using webpack v4 or later, you'll need to install the [CLI](/api/cli/). + +``` bash +npm install --save-dev webpack-cli +``` + +Installing locally is what we recommend for most projects. This makes it easier to upgrade projects individually when breaking changes are introduced. Typically webpack is run via one or more [npm scripts](https://docs.npmjs.com/misc/scripts) which will look for a webpack installation in your local `node_modules` directory: + +```json +"scripts": { + "start": "webpack --config webpack.config.js" +} +``` + +T> To run the local installation of webpack you can access its bin version as `node_modules/.bin/webpack`. + + +## Global Installation + +The following NPM installation will make `webpack` available globally: + +``` bash +npm install --global webpack +``` + +W> Note that this is __not a recommended practice__. Installing globally locks you down to a specific version of webpack and could fail in projects that use a different version. + + +## Bleeding Edge + +If you are enthusiastic about using the latest that webpack has to offer, you can install beta versions or even directly from the webpack repository using the following commands: + +``` bash +npm install webpack@beta +npm install webpack/webpack#<tagname/branchname> +``` + +W> Take caution when installing these bleeding edge releases! They may still contain bugs and therefore should not be used in production. + + +# Getting Started + +Webpack is used to compile JavaScript modules. Once [installed](/guides/installation), you can interface with webpack either from its [CLI](/api/cli) or [API](/api/node). If you're still new to webpack, please read through the [core concepts](/concepts) and [this comparison](/comparison) to learn why you might use it over the other tools that are out in the community. + +## Basic Setup + +First let's create a directory, initialize npm, [install webpack locally](/guides/installation#local-installation), and install the webpack-cli (the tool used to run webpack on the command line): + +``` bash +mkdir webpack-demo && cd webpack-demo +npm init -y +npm install webpack webpack-cli --save-dev +``` + +T> Throughout the Guides we will use `diff` blocks to show you what changes we're making to directories, files, and code. + +Now we'll create the following directory structure, files and their contents: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- index.html ++ |- /src ++ |- index.js +``` + +__src/index.js__ + +``` javascript +function component() { + let element = document.createElement('div'); + + // Lodash, currently included via a script, is required for this line to work + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; +} + +document.body.appendChild(component()); +``` + +__index.html__ + +``` html +<!doctype html> +<html> + <head> + <title>Getting Started</title> + <script src="https://unpkg.com/lodash@4.16.6"></script> + </head> + <body> + <script src="./src/index.js"></script> + </body> +</html> +``` + +We also need to adjust our `package.json` file in order to make sure we mark our package as `private`, as well as removing the `main` entry. This is to prevent an accidental publish of your code. + +T> If you want to learn more about the inner workings of `package.json`, then we recommend reading the [npm documentation](https://docs.npmjs.com/files/package.json). + +__package.json__ + +``` diff + { + "name": "webpack-demo", + "version": "1.0.0", + "description": "", ++ "private": true, +- "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "webpack": "^4.20.2", + "webpack-cli": "^3.1.2" + }, + "dependencies": {} + } +``` + +In this example, there are implicit dependencies between the `<script>` tags. Our `index.js` file depends on `lodash` being included in the page before it runs. This is because `index.js` never explicitly declared a need for `lodash`; it just assumes that the global variable `_` exists. + +There are problems with managing JavaScript projects this way: + +- It is not immediately apparent that the script depends on an external library. +- If a dependency is missing, or included in the wrong order, the application will not function properly. +- If a dependency is included but not used, the browser will be forced to download unnecessary code. + +Let's use webpack to manage these scripts instead. + +## Creating a Bundle + +First we'll tweak our directory structure slightly, separating the "source" code (`/src`) from our "distribution" code (`/dist`). The "source" code is the code that we'll write and edit. The "distribution" code is the minimized and optimized `output` of our build process that will eventually be loaded in the browser: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- /dist ++ |- index.html +- |- index.html + |- /src + |- index.js +``` + +To bundle the `lodash` dependency with `index.js`, we'll need to install the library locally: + +``` bash +npm install --save lodash +``` + +T> When installing a package that will be bundled into your production bundle, you should use `npm install --save`. If you're installing a package for development purposes (e.g. a linter, testing libraries, etc.) then you should use `npm install --save-dev`. More information can be found in the [npm documentation](https://docs.npmjs.com/cli/install). + +Now, lets import `lodash` in our script: + +__src/index.js__ + +``` diff ++ import _ from 'lodash'; ++ + function component() { + let element = document.createElement('div'); + +- // Lodash, currently included via a script, is required for this line to work + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +Now, since we'll be bundling our scripts, we have to update our `index.html` file. Let's remove the lodash `<script>`, as we now `import` it, and modify the other `<script>` tag to load the bundle, instead of the raw `/src` file: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> + <title>Getting Started</title> +- <script src="https://unpkg.com/lodash@4.16.6"></script> + </head> + <body> +- <script src="./src/index.js"></script> ++ <script src="main.js"></script> + </body> + </html> +``` + +In this setup, `index.js` explicitly requires `lodash` to be present, and binds it as `_` (no global scope pollution). By stating what dependencies a module needs, webpack can use this information to build a dependency graph. It then uses the graph to generate an optimized bundle where scripts will be executed in the correct order. + +With that said, let's run `npx webpack`, which will take our script at `src/index.js` as the [entry point](/concepts/entry-points), and will generate `dist/main.js` as the [output](/concepts/output). The `npx` command, which ships with Node 8.2/npm 5.2.0 or higher, runs the webpack binary (`./node_modules/.bin/webpack`) of the webpack package we installed in the beginning: + +``` bash +npx webpack + +... +Built at: 13/06/2018 11:52:07 + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ +``` + +T> Your output may vary a bit, but if the build is successful then you are good to go. Also, don't worry about the warning, we'll tackle that later. + +Open `index.html` in your browser and, if everything went right, you should see the following text: 'Hello webpack'. + + +## Modules + +The [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) statements have been standardized in [ES2015](https://babeljs.io/learn-es2015/) and [are supported in most browsers](https://caniuse.com/#search=modules). Some older browsers still lag behind but webpack supports modules out of the box. + +Behind the scenes, webpack actually "transpiles" the code so that older browsers can also run it. If you inspect `dist/main.js`, you might be able to see how webpack does this, it's quite ingenious! Besides `import` and `export`, webpack supports various other module syntaxes as well, see [Module API](/api/module-methods) for more information. + +Note that webpack will not alter any code other than `import` and `export` statements. If you are using other [ES2015 features](http://es6-features.org/), make sure to [use a transpiler](/loaders/#transpiling) such as [Babel](https://babeljs.io/) or [Bublé](https://buble.surge.sh/guide/) via webpack's [loader system](/concepts/loaders/). + + +## Using a Configuration + +As of version 4, webpack doesn't require any configuration, but most projects will need a more complex setup, which is why webpack supports a [configuration file](/concepts/configuration). This is much more efficient than having to manually type in a lot of commands in the terminal, so let's create one: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- webpack.config.js + |- /dist + |- index.html + |- /src + |- index.js +``` + +__webpack.config.js__ + +``` javascript +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'main.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +Now, let's run the build again but instead using our new configuration file: + +``` bash +npx webpack --config webpack.config.js + +... + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ +``` + +T> If a `webpack.config.js` is present, the `webpack` command picks it up by default. We use the `--config` option here only to show that you can pass a config of any name. This will be useful for more complex configurations that need to be split into multiple files. + +A configuration file allows far more flexibility than simple CLI usage. We can specify loader rules, plugins, resolve options and many other enhancements this way. See the [configuration documentation](/configuration) to learn more. + + +## NPM Scripts + +Given it's not particularly fun to run a local copy of webpack from the CLI, we can set up a little shortcut. Let's adjust our _package.json_ by adding an [npm script](https://docs.npmjs.com/misc/scripts): + +__package.json__ + +``` diff + { + "name": "webpack-demo", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", ++ "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "webpack": "^4.20.2", + "webpack-cli": "^3.1.2" + }, + "dependencies": { + "lodash": "^4.17.5" + } + } +``` + +Now the `npm run build` command can be used in place of the `npx` command we used earlier. Note that within `scripts` we can reference locally installed npm packages by name the same way we did with `npx`. This convention is the standard in most npm-based projects because it allows all contributors to use the same set of common scripts (each with flags like `--config` if necessary). + +Now run the following command and see if your script alias works: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +main.js 70.4 KiB 0 [emitted] main +... + +WARNING in configuration +The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. +You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/. +``` + +T> Custom parameters can be passed to webpack by adding two dashes between the `npm run build` command and your parameters, e.g. `npm run build -- --colors`. + + +## Conclusion + +Now that you have a basic build together you should move on to the next guide [`Asset Management`](/guides/asset-management) to learn how to manage assets like images and fonts with webpack. At this point, your project should look like this: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist + |- main.js + |- index.html +|- /src + |- index.js +|- /node_modules +``` + +T> If you're using npm 5, you'll probably also see a `package-lock.json` file in your directory. + +If you want to learn more about webpack's design, you can check out the [basic concepts](/concepts) and [configuration](/configuration) pages. Furthermore, the [API](/api) section digs into the various interfaces webpack offers. + + +# Asset Management + +If you've been following the guides from the start, you will now have a small project that shows "Hello webpack". Now let's try to incorporate some other assets, like images, to see how they can be handled. + +Prior to webpack, front-end developers would use tools like grunt and gulp to process these assets and move them from their `/src` folder into their `/dist` or `/build` directory. The same idea was used for JavaScript modules, but tools like webpack will __dynamically bundle__ all dependencies (creating what's known as a [dependency graph](/concepts/dependency-graph)). This is great because every module now _explicitly states its dependencies_ and we'll avoid bundling modules that aren't in use. + +One of the coolest webpack features is that you can also _include any other type of file_, besides JavaScript, for which there is a loader. This means that the same benefits listed above for JavaScript (e.g. explicit dependencies) can be applied to everything used in building a website or web app. Let's start with CSS, as you may already be familiar with that setup. + +## Setup + +Let's make a minor change to our project before we get started: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> +- <title>Getting Started</title> ++ <title>Asset Management</title> + </head> + <body> +- <script src="./main.js"></script> ++ <script src="./bundle.js"></script> + </body> + </html> +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { +- filename: 'main.js', ++ filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + + +## Loading CSS + +In order to `import` a CSS file from within a JavaScript module, you need to install and add the [style-loader](/loaders/style-loader) and [css-loader](/loaders/css-loader) to your [`module` configuration](/configuration/module): + +``` bash +npm install --save-dev style-loader css-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ module: { ++ rules: [ ++ { ++ test: /\.css$/, ++ use: [ ++ 'style-loader', ++ 'css-loader' ++ ] ++ } ++ ] ++ } + }; +``` + +T> webpack uses a regular expression to determine which files it should look for and serve to a specific loader. In this case any file that ends with `.css` will be served to the `style-loader` and the `css-loader`. + +This enables you to `import './style.css'` into the file that depends on that styling. Now, when that module is run, a `<style>` tag with the stringified css will be inserted into the `<head>` of your html file. + +Let's try it out by adding a new `style.css` file to our project and import it in our `index.js`: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- style.css + |- index.js + |- /node_modules +``` + +__src/style.css__ + +``` css +.hello { + color: red; +} +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import './style.css'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.classList.add('hello'); + + return element; + } + + document.body.appendChild(component()); +``` + +Now run your build command: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +bundle.js 76.4 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +Open up `index.html` in your browser again and you should see that `Hello webpack` is now styled in red. To see what webpack did, inspect the page (don't view the page source, as it won't show you the result) and look at the page's head tags. It should contain our style block that we imported in `index.js`. + +Note that you can, and in most cases should, [minimize css](/plugins/mini-css-extract-plugin/#minimizing-for-production) for better load times in production. On top of that, loaders exist for pretty much any flavor of CSS you can think of -- [postcss](/loaders/postcss-loader), [sass](/loaders/sass-loader), and [less](/loaders/less-loader) to name a few. + + +## Loading Images + +So now we're pulling in our CSS, but what about our images like backgrounds and icons? Using the [file-loader](/loaders/file-loader) we can easily incorporate those in our system as well: + +``` bash +npm install --save-dev file-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, ++ { ++ test: /\.(png|svg|jpg|gif)$/, ++ use: [ ++ 'file-loader' ++ ] ++ } + ] + } + }; +``` + +Now, when you `import MyImage from './my-image.png'`, that image will be processed and added to your `output` directory _and_ the `MyImage` variable will contain the final url of that image after processing. When using the [css-loader](/loaders/css-loader), as shown above, a similar process will occur for `url('./my-image.png')` within your CSS. The loader will recognize this is a local file, and replace the `'./my-image.png'` path with the final path to the image in your `output` directory. The [html-loader](/loaders/html-loader) handles `<img src="./my-image.png" />` in the same manner. + +Let's add an image to our project and see how this works, you can use any image you like: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; + import './style.css'; ++ import Icon from './icon.png'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + element.classList.add('hello'); + ++ // Add the image to our existing div. ++ var myIcon = new Image(); ++ myIcon.src = Icon; ++ ++ element.appendChild(myIcon); + + return element; + } + + document.body.appendChild(component()); +``` + +__src/style.css__ + +``` diff + .hello { + color: red; ++ background: url('./icon.png'); + } +``` + +Let's create a new build and open up the index.html file again: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] + bundle.js 76.7 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +If all went well, you should now see your icon as a repeating background, as well as an `img` element beside our `Hello webpack` text. If you inspect this element, you'll see that the actual filename has changed to something like `5c999da72346a995e7e2718865d019c8.png`. This means webpack found our file in the `src` folder and processed it! + +T> A logical next step from here is minifying and optimizing your images. Check out the [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader) and [url-loader](/loaders/url-loader) for more on how you can enhance your image loading process. + + +## Loading Fonts + +So what about other assets like fonts? The file and url loaders will take any file you load through them and output it to your build directory. This means we can use them for any kind of file, including fonts. Let's update our `webpack.config.js` to handle font files: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + }, ++ { ++ test: /\.(woff|woff2|eot|ttf|otf)$/, ++ use: [ ++ 'file-loader' ++ ] ++ } + ] + } + }; +``` + +Add some font files to your project: + +__project__ + + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- my-font.woff ++ |- my-font.woff2 + |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +With the loader configured and fonts in place, you can incorporate them via an `@font-face` declaration. The local `url(...)` directive will be picked up by webpack just as it was with the image: + +__src/style.css__ + +``` diff ++ @font-face { ++ font-family: 'MyFont'; ++ src: url('./my-font.woff2') format('woff2'), ++ url('./my-font.woff') format('woff'); ++ font-weight: 600; ++ font-style: normal; ++ } + + .hello { + color: red; ++ font-family: 'MyFont'; + background: url('./icon.png'); + } +``` + +Now run a new build and let's see if webpack handled our fonts: + +``` bash +npm run build + +... + Asset Size Chunks Chunk Names +5439466351d432b73fdb518c6ae9654a.woff2 19.5 KiB [emitted] + 387c65cc923ad19790469cfb5b7cb583.woff 23.4 KiB [emitted] + da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] + bundle.js 77 KiB 0 [emitted] main +Entrypoint main = bundle.js +... +``` + +Open up `index.html` again and see if our `Hello webpack` text has changed to the new font. If all is well, you should see the changes. + + +## Loading Data + +Another useful asset that can be loaded is data, like JSON files, CSVs, TSVs, and XML. Support for JSON is actually built-in, similar to NodeJS, meaning `import Data from './data.json'` will work by default. To import CSVs, TSVs, and XML you could use the [csv-loader](https://github.com/theplatapi/csv-loader) and [xml-loader](https://github.com/gisikw/xml-loader). Let's handle loading all three: + +``` bash +npm install --save-dev csv-loader xml-loader +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + }, + { + test: /\.(woff|woff2|eot|ttf|otf)$/, + use: [ + 'file-loader' + ] + }, ++ { ++ test: /\.(csv|tsv)$/, ++ use: [ ++ 'csv-loader' ++ ] ++ }, ++ { ++ test: /\.xml$/, ++ use: [ ++ 'xml-loader' ++ ] ++ } + ] + } + }; +``` + +Add some data files to your project: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src ++ |- data.xml + |- my-font.woff + |- my-font.woff2 + |- icon.png + |- style.css + |- index.js + |- /node_modules +``` + +__src/data.xml__ + +``` xml +<?xml version="1.0" encoding="UTF-8"?> +<note> + <to>Mary</to> + <from>John</from> + <heading>Reminder</heading> + <body>Call Cindy on Tuesday</body> +</note> +``` + +Now you can `import` any one of those four types of data (JSON, CSV, TSV, XML) and the `Data` variable you import it to will contain parsed JSON for easy consumption: + +__src/index.js__ + +``` diff + import _ from 'lodash'; + import './style.css'; + import Icon from './icon.png'; ++ import Data from './data.xml'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + element.classList.add('hello'); + + // Add the image to our existing div. + var myIcon = new Image(); + myIcon.src = Icon; + + element.appendChild(myIcon); + ++ console.log(Data); + + return element; + } + + document.body.appendChild(component()); +``` + +When you open `index.html` and look at your console in your developer tools, you should be able to see your imported data being logged to the console! + +T> This can be especially helpful when implementing some sort of data visualization using a tool like [d3](https://github.com/d3). Instead of making an ajax request and parsing the data at runtime you can load it into your module during the build process so that the parsed data is ready to go as soon as the module hits the browser. + + +## Global Assets + +The coolest part of everything mentioned above, is that loading assets this way allows you to group modules and assets together in a more intuitive way. Instead of relying on a global `/assets` directory that contains everything, you can group assets with the code that uses them. For example, a structure like this can be very useful: + +``` diff +- |- /assets ++ |– /components ++ | |– /my-component ++ | | |– index.jsx ++ | | |– index.css ++ | | |– icon.svg ++ | | |– img.png +``` + +This setup makes your code a lot more portable as everything that is closely coupled now lives together. Let's say you want to use `/my-component` in another project, simply copy or move it into the `/components` directory over there. As long as you've installed any _external dependencies_ and your _configuration has the same loaders_ defined, you should be good to go. + +However, let's say you're locked into your old ways or you have some assets that are shared between multiple components (views, templates, modules, etc.). It's still possible to store these assets in a base directory and even use [aliasing](/configuration/resolve#resolve-alias) to make them easier to `import`. + + +## Wrapping up + +For the next guides we won't be using all the different assets we've used in this guide, so let's do some cleanup so we're prepared for the next piece of the guides [Output Management](https://webpack.js.org/guides/output-management/): + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src +- |- data.xml +- |- my-font.woff +- |- my-font.woff2 +- |- icon.png +- |- style.css + |- index.js + |- /node_modules +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- module: { +- rules: [ +- { +- test: /\.css$/, +- use: [ +- 'style-loader', +- 'css-loader' +- ] +- }, +- { +- test: /\.(png|svg|jpg|gif)$/, +- use: [ +- 'file-loader' +- ] +- }, +- { +- test: /\.(woff|woff2|eot|ttf|otf)$/, +- use: [ +- 'file-loader' +- ] +- }, +- { +- test: /\.(csv|tsv)$/, +- use: [ +- 'csv-loader' +- ] +- }, +- { +- test: /\.xml$/, +- use: [ +- 'xml-loader' +- ] +- } +- ] +- } + }; +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; +- import './style.css'; +- import Icon from './icon.png'; +- import Data from './data.xml'; +- + function component() { + var element = document.createElement('div'); +- +- // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- element.classList.add('hello'); +- +- // Add the image to our existing div. +- var myIcon = new Image(); +- myIcon.src = Icon; +- +- element.appendChild(myIcon); +- +- console.log(Data); + + return element; + } + + document.body.appendChild(component()); +``` + + +## Next guide + +Let's move on to [Output Management](https://webpack.js.org/guides/output-management/) + + +## Further Reading + +- [Loading Fonts](https://survivejs.com/webpack/loading/fonts/) on SurviveJS + + +# Output Management + +T> This guide extends on code examples found in the [`Asset Management`](/guides/asset-management) guide. + +So far we've manually included all our assets in our `index.html` file, but as your application grows and once you start [using hashes in filenames](/guides/caching) and outputting [multiple bundles](/guides/code-splitting), it will be difficult to keep managing your `index.html` file manually. However, a few plugins exist that will make this process much easier to manage. + +## Preparation + +First, let's adjust our project a little bit: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js ++ |- print.js + |- /node_modules +``` + +Let's add some logic to our `src/print.js` file: + +__src/print.js__ + +``` js +export default function printMe() { + console.log('I get called from print.js!'); +} +``` + +And use that function in our `src/index.js` file: + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); ++ var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + ++ btn.innerHTML = 'Click me and check the console!'; ++ btn.onclick = printMe; ++ ++ element.appendChild(btn); + + return element; + } + + document.body.appendChild(component()); +``` + +Let's also update our `dist/index.html` file, in preparation for webpack to split out entries: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> +- <title>Asset Management</title> ++ <title>Output Management</title> ++ <script src="./print.bundle.js"></script> + </head> + <body> +- <script src="./bundle.js"></script> ++ <script src="./app.bundle.js"></script> + </body> + </html> +``` + +Now adjust the config. We'll be adding our `src/print.js` as a new entry point (`print`) and we'll change the output as well, so that it will dynamically generate bundle names, based on the entry point names: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { +- entry: './src/index.js', ++ entry: { ++ app: './src/index.js', ++ print: './src/print.js' ++ }, + output: { +- filename: 'bundle.js', ++ filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Let's run `npm run build` and see what this generates: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 545 kB 0, 1 [emitted] [big] app +print.bundle.js 2.74 kB 1 [emitted] print +... +``` + +We can see that webpack generates our `print.bundle.js` and `app.bundle.js` files, which we also specified in our `index.html` file. if you open `index.html` in your browser, you can see what happens when you click the button. + +But what would happen if we changed the name of one of our entry points, or even added a new one? The generated bundles would be renamed on a build, but our `index.html` file would still reference the old names. Let's fix that with the [`HtmlWebpackPlugin`](/plugins/html-webpack-plugin). + + +## Setting up HtmlWebpackPlugin + +First install the plugin and adjust the `webpack.config.js` file: + +``` bash +npm install --save-dev html-webpack-plugin +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, ++ plugins: [ ++ new HtmlWebpackPlugin({ ++ title: 'Output Management' ++ }) ++ ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Before we do a build, you should know that the `HtmlWebpackPlugin` by default will generate its own `index.html` file, even though we already have one in the `dist/` folder. This means that it will replace our `index.html` file with a newly generated one. Let's see what happens when we do an `npm run build`: + +``` bash +... + Asset Size Chunks Chunk Names + print.bundle.js 544 kB 0 [emitted] [big] print + app.bundle.js 2.81 kB 1 [emitted] app + index.html 249 bytes [emitted] +... +``` + +If you open `index.html` in your code editor, you'll see that the `HtmlWebpackPlugin` has created an entirely new file for you and that all the bundles are automatically added. + +If you want to learn more about all the features and options that the `HtmlWebpackPlugin` provides, then you should read up on it on the [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin) repo. + +You can also take a look at [`html-webpack-template`](https://github.com/jaketrent/html-webpack-template) which provides a couple of extra features in addition to the default template. + + +## Cleaning up the `/dist` folder + +As you might have noticed over the past guides and code example, our `/dist` folder has become quite cluttered. Webpack will generate the files and put them in the `/dist` folder for you, but it doesn't keep track of which files are actually in use by your project. + +In general it's good practice to clean the `/dist` folder before each build, so that only used files will be generated. Let's take care of that. + +A popular plugin to manage this is the [`clean-webpack-plugin`](https://www.npmjs.com/package/clean-webpack-plugin) so let's install and configure it. + +``` bash +npm install --save-dev clean-webpack-plugin +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); ++ const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ ++ new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Output Management' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Now run an `npm run build` and inspect the `/dist` folder. If everything went well you should now only see the files generated from the build and no more old files! + + +## The Manifest + +You might be wondering how webpack and its plugins seem to "know" what files are being generated. The answer is in the manifest that webpack keeps to track how all the modules map to the output bundles. If you're interested in managing webpack's [`output`](/configuration/output) in other ways, the manifest would be a good place to start. + +The manifest data can be extracted into a json file for easy consumption using the [`WebpackManifestPlugin`](https://github.com/danethurber/webpack-manifest-plugin). + +We won't go through a full example of how to use this plugin within your projects, but you can read up on [the concept page](/concepts/manifest) and the [caching guide](/guides/caching) to find out how this ties into long term caching. + + +## Conclusion + +Now that you've learned about dynamically adding bundles to your HTML, let's dive into the [development guide](/guides/development). Or, if you want to dig into more advanced topics, we would recommend heading over to the [code splitting guide](/guides/code-splitting). + + +# Development + +T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. + +If you've been following the guides, you should have a solid understanding of some of the webpack basics. Before we continue, let's look into setting up a development environment to make our lives a little easier. + +W> The tools in this guide are __only meant for development__, please __avoid__ using them in production! + +Before proceeding lets first set [`mode` to `'development'`](/concepts/mode/#mode-development). + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { ++ mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +## Using source maps + +When webpack bundles your source code, it can become difficult to track down errors and warnings to their original location. For example, if you bundle three source files (`a.js`, `b.js`, and `c.js`) into one bundle (`bundle.js`) and one of the source files contains an error, the stack trace will simply point to `bundle.js`. This isn't always helpful as you probably want to know exactly which source file the error came from. + +In order to make it easier to track down errors and warnings, JavaScript offers [source maps](http://blog.teamtreehouse.com/introduction-source-maps), which maps your compiled code back to your original source code. If an error originates from `b.js`, the source map will tell you exactly that. + +There are a lot of [different options](/configuration/devtool) available when it comes to source maps. Be sure to check them out so you can configure them to your needs. + +For this guide, let's use the `inline-source-map` option, which is good for illustrative purposes (though not for production): + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, ++ devtool: 'inline-source-map', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Now let's make sure we have something to debug, so let's create an error in our `print.js` file: + +__src/print.js__ + +``` diff + export default function printMe() { +- console.log('I get called from print.js!'); ++ cosnole.log('I get called from print.js!'); + } +``` + +Run an `npm run build`, it should compile to something like this: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 1.44 MB 0, 1 [emitted] [big] app +print.bundle.js 6.43 kB 1 [emitted] print + index.html 248 bytes [emitted] +... +``` + +Now open the resulting `index.html` file in your browser. Click the button and look in your console where the error is displayed. The error should say something like this: + + ``` bash + Uncaught ReferenceError: cosnole is not defined + at HTMLButtonElement.printMe (print.js:2) + ``` + +We can see that the error also contains a reference to the file (`print.js`) and line number (2) where the error occurred. This is great because now we know exactly where to look in order to fix the issue. + + +## Choosing a Development Tool + +W> Some text editors have a "safe write" function that might interfere with some of the following tools. Read [Adjusting Your text Editor](#adjusting-your-text-editor) for a solution to these issues. + +It quickly becomes a hassle to manually run `npm run build` every time you want to compile your code. + +There are a couple of different options available in webpack that help you automatically compile your code whenever it changes: + + 1. webpack's Watch Mode + 2. webpack-dev-server + 3. webpack-dev-middleware + +In most cases, you probably would want to use `webpack-dev-server`, but let's explore all of the above options. + + +### Using Watch Mode + +You can instruct webpack to "watch" all files within your dependency graph for changes. If one of these files is updated, the code will be recompiled so you don't have to run the full build manually. + +Let's add an npm script that will start webpack's Watch Mode: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", ++ "watch": "webpack --watch", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now run `npm run watch` from the command line and see how webpack compiles your code. +You can see that it doesn't exit the command line because the script is currently watching your files. + +Now, while webpack is watching your files, let's remove the error we introduced earlier: + +__src/print.js__ + +``` diff + export default function printMe() { +- cosnole.log('I get called from print.js!'); ++ console.log('I get called from print.js!'); + } +``` + +Now save your file and check the terminal window. You should see that webpack automatically recompiles the changed module! + +The only downside is that you have to refresh your browser in order to see the changes. It would be much nicer if that would happen automatically as well, so let's try `webpack-dev-server` which will do exactly that. + + +### Using webpack-dev-server + +The `webpack-dev-server` provides you with a simple web server and the ability to use live reloading. Let's set it up: + +``` bash +npm install --save-dev webpack-dev-server +``` + +Change your config file to tell the dev server where to look for files: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + devtool: 'inline-source-map', ++ devServer: { ++ contentBase: './dist' ++ }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Development' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +This tells `webpack-dev-server` to serve the files from the `dist` directory on `localhost:8080`. + +W> webpack-dev-server doesn't write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server's root path. If your page expects to find the bundle files in different path, you can change this with the [`publicPath`](/configuration/dev-server/#devserver-publicpath-) option in the dev server's configuration. + +Let's add a script to easily run the dev server as well: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "watch": "webpack --watch", ++ "start": "webpack-dev-server --open", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now we can run `npm start` from the command line and we will see our browser automatically loading up our page. If you now change any of the source files and save them, the web server will automatically reload after the code has been compiled. Give it a try! + +The `webpack-dev-server` comes with many configurable options. Head over to the [documentation](/configuration/dev-server) to learn more. + +T> Now that your server is working, you might want to give [Hot Module Replacement](/guides/hot-module-replacement) a try! + + +### Using webpack-dev-middleware + +`webpack-dev-middleware` is a wrapper that will emit files processed by webpack to a server. This is used in `webpack-dev-server` internally, however it's available as a separate package to allow more custom setups if desired. We'll take a look at an example that combines webpack-dev-middleware with an express server. + +Let's install `express` and `webpack-dev-middleware` so we can get started: + +``` bash +npm install --save-dev express webpack-dev-middleware +``` + +Now we need to make some adjustments to our webpack configuration file in order to make sure the middleware will function correctly: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + + module.exports = { + mode: 'development', + entry: { + app: './src/index.js', + print: './src/print.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Output Management' + }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist'), ++ publicPath: '/' + } + }; +``` + +The `publicPath` will be used within our server script as well in order to make sure files are served correctly on `http://localhost:3000`. We'll specify the port number later. The next step is setting up our custom `express` server: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js ++ |- server.js + |- /dist + |- /src + |- index.js + |- print.js + |- /node_modules +``` + +__server.js__ + +```javascript +const express = require('express'); +const webpack = require('webpack'); +const webpackDevMiddleware = require('webpack-dev-middleware'); + +const app = express(); +const config = require('./webpack.config.js'); +const compiler = webpack(config); + +// Tell express to use the webpack-dev-middleware and use the webpack.config.js +// configuration file as a base. +app.use(webpackDevMiddleware(compiler, { + publicPath: config.output.publicPath +})); + +// Serve the files on port 3000. +app.listen(3000, function () { + console.log('Example app listening on port 3000!\n'); +}); +``` + +Now add an npm script to make it a little easier to run the server: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "watch": "webpack --watch", + "start": "webpack-dev-server --open", ++ "server": "node server.js", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.16", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "express": "^4.15.3", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "webpack-dev-middleware": "^1.12.0", + "xml-loader": "^1.2.1" + } + } +``` + +Now in your terminal run `npm run server`, it should give you an output similar to this: + +``` bash +Example app listening on port 3000! +... + Asset Size Chunks Chunk Names + app.bundle.js 1.44 MB 0, 1 [emitted] [big] app +print.bundle.js 6.57 kB 1 [emitted] print + index.html 306 bytes [emitted] +... +webpack: Compiled successfully. +``` + +Now fire up your browser and go to `http://localhost:3000`. You should see your webpack app running and functioning! + +T> If you would like to know more about how Hot Module Replacement works, we recommend you read the [Hot Module Replacement](/guides/hot-module-replacement/) guide. + + +## Adjusting Your Text Editor + +When using automatic compilation of your code, you could run into issues when saving your files. Some editors have a "safe write" feature that can potentially interfere with recompilation. + +To disable this feature in some common editors, see the list below: + +- __Sublime Text 3__: Add `atomic_save: 'false'` to your user preferences. +- __JetBrains IDEs (e.g. WebStorm)__: Uncheck "Use safe write" in `Preferences > Appearance & Behavior > System Settings`. +- __Vim__: Add `:set backupcopy=yes` to your settings. + + +## Conclusion + +Now that you've learned how to automatically compile your code and run a simple development server, you can check out the next guide, which will cover [Hot Module Replacement](/guides/hot-module-replacement). + + +# Hot Module Replacement + +T> This guide extends on code examples found in the [Development](/guides/development) guide. + +Hot Module Replacement (or HMR) is one of the most useful features offered by webpack. It allows all kinds of modules to be updated at runtime without the need for a full refresh. This page focuses on __implementation__ while the [concepts page](/concepts/hot-module-replacement) gives more details on how it works and why it's useful. + +W> __HMR__ is not intended for use in production, meaning it should only be used in development. See the [building for production guide](/guides/production) for more information. + + +## Enabling HMR + +This feature is great for productivity. All we need to do is update our [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration, and use webpack's built in HMR plugin. We'll also remove the entry point for `print.js` as it will now be consumed by the `index.js` module. + +T> If you took the route of using `webpack-dev-middleware` instead of `webpack-dev-server`, please use the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom server or application. + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const webpack = require('webpack'); + + module.exports = { + entry: { +- app: './src/index.js', +- print: './src/print.js' ++ app: './src/index.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist', ++ hot: true + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Hot Module Replacement' + }), ++ new webpack.HotModuleReplacementPlugin() + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +T> You can use the CLI to modify the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration with the following command: `webpack-dev-server --hotOnly`. + +Now let's update the `index.js` file so that when a change inside `print.js` is detected we tell webpack to accept the updated module. + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; + + element.appendChild(btn); + + return element; + } + + document.body.appendChild(component()); ++ ++ if (module.hot) { ++ module.hot.accept('./print.js', function() { ++ console.log('Accepting the updated printMe module!'); ++ printMe(); ++ }) ++ } +``` + +Start changing the `console.log` statement in `print.js`, and you should see the following output in the browser console. + +__print.js__ + +``` diff + export default function printMe() { +- console.log('I get called from print.js!'); ++ console.log('Updating print.js...') + } +``` + +__console__ + +``` diff +[HMR] Waiting for update signal from WDS... +main.js:4395 [WDS] Hot Module Replacement enabled. ++ 2main.js:4395 [WDS] App updated. Recompiling... ++ main.js:4395 [WDS] App hot update... ++ main.js:4330 [HMR] Checking for updates on the server... ++ main.js:10024 Accepting the updated printMe module! ++ 0.4b8ee77….hot-update.js:10 Updating print.js... ++ main.js:4330 [HMR] Updated modules: ++ main.js:4330 [HMR] - 20 +``` + + +## Via the Node.js API + +When using Webpack Dev Server with the Node.js API, don't put the dev server options on the webpack config object. Instead, pass them as a second parameter upon creation. For example: + +`new WebpackDevServer(compiler, options)` + +To enable HMR, you also need to modify your webpack configuration object to include the HMR entry points. The `webpack-dev-server` package includes a method called `addDevServerEntrypoints` which you can use to do this. Here's a small example of how that might look: + +__dev-server.js__ + +``` javascript +const webpackDevServer = require('webpack-dev-server'); +const webpack = require('webpack'); + +const config = require('./webpack.config.js'); +const options = { + contentBase: './dist', + hot: true, + host: 'localhost' +}; + +webpackDevServer.addDevServerEntrypoints(config, options); +const compiler = webpack(config); +const server = new webpackDevServer(compiler, options); + +server.listen(5000, 'localhost', () => { + console.log('dev server listening on port 5000'); +}); +``` + +T> If you're [using `webpack-dev-middleware`](/guides/development#using-webpack-dev-middleware), check out the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom dev server. + + +## Gotchas + +Hot Module Replacement can be tricky. To show this, let's go back to our working example. If you go ahead and click the button on the example page, you will realize the console is printing the old `printMe` function. + +This is happening because the button's `onclick` event handler is still bound to the original `printMe` function. + +To make this work with HMR we need to update that binding to the new `printMe` function using `module.hot.accept`: + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; // onclick event is bind to the original printMe function + + element.appendChild(btn); + + return element; + } + +- document.body.appendChild(component()); ++ let element = component(); // Store the element to re-render on print.js changes ++ document.body.appendChild(element); + + if (module.hot) { + module.hot.accept('./print.js', function() { + console.log('Accepting the updated printMe module!'); +- printMe(); ++ document.body.removeChild(element); ++ element = component(); // Re-render the "component" to update the click handler ++ document.body.appendChild(element); + }) + } +``` + +This is just one example, but there are many others that can easily trip people up. Luckily, there are a lot of loaders out there (some of which are mentioned below) that will make hot module replacement much easier. + + +## HMR with Stylesheets + +Hot Module Replacement with CSS is actually fairly straightforward with the help of the `style-loader`. This loader uses `module.hot.accept` behind the scenes to patch `<style>` tags when CSS dependencies are updated. + +First let's install both loaders with the following command: + +```bash +npm install --save-dev style-loader css-loader +``` + +Now let's update the configuration file to make use of the loader. + +__webpack.config.js__ + +```diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const webpack = require('webpack'); + + module.exports = { + entry: { + app: './src/index.js' + }, + devtool: 'inline-source-map', + devServer: { + contentBase: './dist', + hot: true + }, ++ module: { ++ rules: [ ++ { ++ test: /\.css$/, ++ use: ['style-loader', 'css-loader'] ++ } ++ ] ++ }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Hot Module Replacement' + }), + new webpack.HotModuleReplacementPlugin() + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Hot loading stylesheets is as easy as importing them into a module: + +__project__ + +``` diff + webpack-demo + | - package.json + | - webpack.config.js + | - /dist + | - bundle.js + | - /src + | - index.js + | - print.js ++ | - styles.css +``` + +__styles.css__ + +``` css +body { + background: blue; +} +``` + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; ++ import './styles.css'; + + function component() { + var element = document.createElement('div'); + var btn = document.createElement('button'); + + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + btn.innerHTML = 'Click me and check the console!'; + btn.onclick = printMe; // onclick event is bind to the original printMe function + + element.appendChild(btn); + + return element; + } + + let element = component(); + document.body.appendChild(element); + + if (module.hot) { + module.hot.accept('./print.js', function() { + console.log('Accepting the updated printMe module!'); + document.body.removeChild(element); + element = component(); // Re-render the "component" to update the click handler + document.body.appendChild(element); + }) + } + +``` + +Change the style on `body` to `background: red;` and you should immediately see the page's background color change without a full refresh. + +__styles.css__ + +``` diff + body { +- background: blue; ++ background: red; + } +``` + + +## Other Code and Frameworks + +There are many other loaders and examples out in the community to make HMR interact smoothly with a variety of frameworks and libraries... + +- [React Hot Loader](https://github.com/gaearon/react-hot-loader): Tweak react components in real time. +- [Vue Loader](https://github.com/vuejs/vue-loader): This loader supports HMR for vue components out of the box. +- [Elm Hot Loader](https://github.com/fluxxu/elm-hot-loader): Supports HMR for the Elm programming language. +- [Angular HMR](https://github.com/gdi2290/angular-hmr): No loader necessary! A simple change to your main NgModule file is all that's required to have full control over the HMR APIs. + +T> If you know of any other loaders or plugins that help with or enhance Hot Module Replacement please submit a pull request to add to this list! + + +# Tree Shaking + +_Tree shaking_ is a term commonly used in the JavaScript context for dead-code elimination. It relies on the [static structure](http://exploringjs.com/es6/ch_modules.html#static-module-structure) of ES2015 module syntax, i.e. [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export). The name and concept have been popularized by the ES2015 module bundler [rollup](https://github.com/rollup/rollup). + +The webpack 2 release came with built-in support for ES2015 modules (alias _harmony modules_) as well as unused module export detection. The new webpack 4 release expands on this capability with a way to provide hints to the compiler via the `"sideEffects"` `package.json` property to denote which files in your project are "pure" and therefore safe to prune if unused. + +T> The remainder of this guide will stem from [Getting Started](/guides/getting-started). If you haven't read through that guide already, please do so now. + + +## Add a Utility + +Let's add a new utility file to our project, `src/math.js`, that exports two functions: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist + |- bundle.js + |- index.html +|- /src + |- index.js ++ |- math.js +|- /node_modules +``` + +__src/math.js__ + +```javascript +export function square(x) { + return x * x; +} + +export function cube(x) { + return x * x * x; +} +``` + +Set the `mode` configuration option to [development](/concepts/mode/#mode-development) to make sure that the bundle is not minified: + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') +- } ++ }, ++ mode: 'development', ++ optimization: { ++ usedExports: true ++ } +}; +``` + +With that in place, let's update our entry script to utilize one of these new methods and remove `lodash` for simplicity: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; ++ import { cube } from './math.js'; + + function component() { +- var element = document.createElement('div'); ++ var element = document.createElement('pre'); + +- // Lodash, now imported by this script +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.innerHTML = [ ++ 'Hello webpack!', ++ '5 cubed is equal to ' + cube(5) ++ ].join('\n\n'); + + return element; + } + + document.body.appendChild(component()); +``` + +Note that we __did not `import` the `square` method__ from the `src/math.js` module. That function is what's known as "dead code", meaning an unused `export` that should be dropped. Now let's run our npm script, `npm run build`, and inspect the output bundle: + +__dist/bundle.js (around lines 90 - 100)__ + +```js +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + 'use strict'; + /* unused harmony export square */ + /* harmony export (immutable) */ __webpack_exports__['a'] = cube; + function square(x) { + return x * x; + } + + function cube(x) { + return x * x * x; + } +}); +``` + +Note the `unused harmony export square` comment above. If you look at the code below it, you'll notice that `square` is not being imported, however, it is still included in the bundle. We'll fix that in the next section. + + +## Mark the file as side-effect-free + +In a 100% ESM module world, identifying side effects is straightforward. However, we aren't there just yet, so in the mean time it's necessary to provide hints to webpack's compiler on the "pureness" of your code. + +The way this is accomplished is the `"sideEffects"` package.json property. + +```json +{ + "name": "your-project", + "sideEffects": false +} +``` + +All the code noted above does not contain side effects, so we can simply mark the property as `false` to inform webpack that it can safely prune unused exports. + +T> A "side effect" is defined as code that performs a special behavior when imported, other than exposing one or more exports. An example of this are polyfills, which affect the global scope and usually do not provide an export. + +If your code did have some side effects though, an array can be provided instead: + +```json +{ + "name": "your-project", + "sideEffects": [ + "./src/some-side-effectful-file.js" + ] +} +``` + +The array accepts relative, absolute, and glob patterns to the relevant files. It uses [micromatch](https://github.com/micromatch/micromatch#matching-features) under the hood. + +T> Note that any imported file is subject to tree shaking. This means if you use something like `css-loader` in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode: + +```json +{ + "name": "your-project", + "sideEffects": [ + "./src/some-side-effectful-file.js", + "*.css" + ] +} +``` + +Finally, `"sideEffects"` can also be set from the [`module.rules` configuration option](/configuration/module/#module-rules). + +## Minify the Output + +So we've cued up our "dead code" to be dropped by using the `import` and `export` syntax, but we still need to drop it from the bundle. To do that set the `mode` configuration option to [`production`](/concepts/mode/#mode-production) configuration option. + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- mode: 'development', +- optimization: { +- usedExports: true +- } ++ mode: 'production' +}; +``` + +T> Note that the `--optimize-minimize` flag can be used to enable `TerserPlugin` as well. + +With that squared away, we can run another `npm run build` and see if anything has changed. + +Notice anything different about `dist/bundle.js`? Clearly the whole bundle is now minified and mangled, but, if you look carefully, you won't see the `square` function included but will see a mangled version of the `cube` function (`function r(e){return e*e*e}n.a=r`). With minification and tree shaking our bundle is now a few bytes smaller! While that may not seem like much in this contrived example, tree shaking can yield a significant decrease in bundle size when working on larger applications with complex dependency trees. + +T> [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) is needed for the tree shaking to work. It is added by `mode: "production"`. If you are not using it, remember to add the [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) manually. + +## Conclusion + +So, what we've learned is that in order to take advantage of _tree shaking_, you must... + +- Use ES2015 module syntax (i.e. `import` and `export`). +- Ensure no compilers transform your ES2015 module syntax into CommonJS modules (this is the default behavior of popular Babel preset @babel/preset-env - see [documentation](https://babeljs.io/docs/en/babel-preset-env#modules) for more details). +- Add a `"sideEffects"` property to your project's `package.json` file. +- Use [`production`](/concepts/mode/#mode-production) `mode` configuration option to enable [various optimizations](/concepts/mode/#usage) including minification and tree shaking. + +You can imagine your application as a tree. The source code and libraries you actually use represent the green, living leaves of the tree. Dead code represents the brown, dead leaves of the tree that are consumed by autumn. In order to get rid of the dead leaves, you have to shake the tree, causing them to fall. + +If you are interested in more ways to optimize your output, please jump to the next guide for details on building for [production](/guides/production). + + +# Production + +In this guide we'll dive into some of the best practices and utilities for building a production site or application. + +T> This walkthrough stems from [Tree Shaking](/guides/tree-shaking) and [Development](/guides/development). Please ensure you are familiar with the concepts/setup introduced in those guides before continuing on. + + +## Setup + +The goals of _development_ and _production_ builds differ greatly. In _development_, we want strong source mapping and a localhost server with live reloading or hot module replacement. In _production_, our goals shift to a focus on minified bundles, lighter weight source maps, and optimized assets to improve load time. With this logical separation at hand, we typically recommend writing __separate webpack configurations__ for each environment. + +While we will separate the _production_ and _development_ specific bits out, note that we'll still maintain a "common" configuration to keep things DRY. In order to merge these configurations together, we'll use a utility called [`webpack-merge`](https://github.com/survivejs/webpack-merge). With the "common" configuration in place, we won't have to duplicate code within the environment-specific configurations. + +Let's start by installing `webpack-merge` and splitting out the bits we've already worked on in previous guides: + +``` bash +npm install --save-dev webpack-merge +``` + +__project__ + +``` diff + webpack-demo + |- package.json +- |- webpack.config.js ++ |- webpack.common.js ++ |- webpack.dev.js ++ |- webpack.prod.js + |- /dist + |- /src + |- index.js + |- math.js + |- /node_modules +``` + +__webpack.common.js__ + +``` diff ++ const path = require('path'); ++ const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const HtmlWebpackPlugin = require('html-webpack-plugin'); ++ ++ module.exports = { ++ entry: { ++ app: './src/index.js' ++ }, ++ plugins: [ ++ new CleanWebpackPlugin(['dist']), ++ new HtmlWebpackPlugin({ ++ title: 'Production' ++ }) ++ ], ++ output: { ++ filename: '[name].bundle.js', ++ path: path.resolve(__dirname, 'dist') ++ } ++ }; +``` + +__webpack.dev.js__ + +``` diff ++ const merge = require('webpack-merge'); ++ const common = require('./webpack.common.js'); ++ ++ module.exports = merge(common, { ++ mode: 'development', ++ devtool: 'inline-source-map', ++ devServer: { ++ contentBase: './dist' ++ } ++ }); +``` + +__webpack.prod.js__ + +``` diff ++ const merge = require('webpack-merge'); ++ const common = require('./webpack.common.js'); ++ ++ module.exports = merge(common, { ++ mode: 'production', ++ }); +``` + +In `webpack.common.js`, we now have setup our `entry` and `output` configuration and we've included any plugins that are required for both environments. In `webpack.dev.js`, we've set ``mode`` to ``development``. Also, we've added the recommended `devtool` for that environment (strong source mapping), as well as our simple `devServer` configuration. Finally, in `webpack.prod.js`,``mode`` is set to ``production`` which loads `TerserPlugin` which was first introduced by the [tree shaking](/guides/tree-shaking) guide. + +Note the use of `merge()` in the environment-specific configurations to easily include our common configuration in `dev` and `prod`. The `webpack-merge` tool offers a variety of advanced features for merging but for our use case we won't need any of that. + + +## NPM Scripts + +Now let's repoint our `scripts` to the new configurations. We'll use the _development_ one for our `webpack-dev-server`, `npm start`, script and the _production_ one for our `npm run build` script: + +__package.json__ + +``` diff + { + "name": "development", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { +- "start": "webpack-dev-server --open", ++ "start": "webpack-dev-server --open --config webpack.dev.js", +- "build": "webpack" ++ "build": "webpack --config webpack.prod.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "clean-webpack-plugin": "^0.1.17", + "css-loader": "^0.28.4", + "csv-loader": "^2.1.1", + "express": "^4.15.3", + "file-loader": "^0.11.2", + "html-webpack-plugin": "^2.29.0", + "style-loader": "^0.18.2", + "webpack": "^3.0.0", + "webpack-dev-middleware": "^1.12.0", + "webpack-dev-server": "^2.9.1", + "webpack-merge": "^4.1.0", + "xml-loader": "^1.2.1" + } + } +``` + +Feel free to run those scripts and see how the output changes as we continue adding to our _production_ configuration. + + +## Specify the Mode + +Many libraries will key off the `process.env.NODE_ENV` variable to determine what should be included in the library. For example, when not in _production_ some libraries may add additional logging and testing to make debugging easier. However, with `process.env.NODE_ENV === 'production'` they might drop or add significant portions of code to optimize how things run for your actual users. Since webpack v4, specifying [`mode`](/concepts/mode/) automatically configures [`DefinePlugin`](/plugins/define-plugin) for you: + +__webpack.prod.js__ + +``` diff + const merge = require('webpack-merge'); + const common = require('./webpack.common.js'); + + module.exports = merge(common, { + mode: 'production', + }); +``` + +T> Technically, `NODE_ENV` is a system environment variable that Node.js exposes into running scripts. It is used by convention to determine dev-vs-prod behavior by server tools, build scripts, and client-side libraries. Contrary to expectations, `process.env.NODE_ENV` is not set to `"production"` __within__ the build script `webpack.config.js`, see [#2537](https://github.com/webpack/webpack/issues/2537). Thus, conditionals like `process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'` within webpack configurations do not work as expected. + +If you're using a library like [`react`](https://reactjs.org/), you should actually see a significant drop in bundle size after adding this plugin. Also note that any of our local `/src` code can key off of this as well, so the following check would be valid: + +__src/index.js__ + +``` diff + import { cube } from './math.js'; ++ ++ if (process.env.NODE_ENV !== 'production') { ++ console.log('Looks like we are in development mode!'); ++ } + + function component() { + var element = document.createElement('pre'); + + element.innerHTML = [ + 'Hello webpack!', + '5 cubed is equal to ' + cube(5) + ].join('\n\n'); + + return element; + } + + document.body.appendChild(component()); +``` + + +## Minification + +webpack v4+ will minify your code by default in [`production mode`](/concepts/mode/#mode-production). + +Note that while the [`TerserPlugin`](/plugins/terser-webpack-plugin) is a great place to start for minification and being used by default, there are other options out there. Here are a few more popular ones: + +- [`BabelMinifyWebpackPlugin`](https://github.com/webpack-contrib/babel-minify-webpack-plugin) +- [`ClosureCompilerPlugin`](https://github.com/roman01la/webpack-closure-compiler) + +If you decide to try another minification plugin, just make sure your new choice also drops dead code as described in the [tree shaking](/guides/tree-shaking) guide and provide it as the [`optimization.minimizer`](/configuration/optimization/#optimization-minimizer). + + +## Source Mapping + +We encourage you to have source maps enabled in production, as they are useful for debugging as well as running benchmark tests. That said, you should choose one with a fairly quick build speed that's recommended for production use (see [`devtool`](/configuration/devtool)). For this guide, we'll use the `source-map` option in _production_ as opposed to the `inline-source-map` we used in _development_: + +__webpack.prod.js__ + +``` diff + const merge = require('webpack-merge'); + const common = require('./webpack.common.js'); + + module.exports = merge(common, { + mode: 'production', ++ devtool: 'source-map' + }); +``` + +T> Avoid `inline-***` and `eval-***` use in production as they can increase bundle size and reduce the overall performance. + + +## Minimize CSS + +It is crucial to minimize your CSS on production, please see [Minimizing for Production](/plugins/mini-css-extract-plugin/#minimizing-for-production) section. + + +## CLI Alternatives + +Some of what has been described above is also achievable via the command line. For example, the `--optimize-minimize` flag will include the `TerserPlugin` behind the scenes. The `--define process.env.NODE_ENV="'production'"` will do the same for the `DefinePlugin` instance described above. And, `webpack -p` will automatically invoke both those flags and thus the plugins to be included. + +While these short hand methods are nice, we usually recommend just using the configuration as it's better to understand exactly what is being done for you in both cases. The configuration also gives you more control on fine tuning other options within both plugins. + + +# Code Splitting + +T> This guide extends the examples provided in [Getting Started](/guides/getting-started) and [Output Management](/guides/output-management). Please make sure you are at least familiar with the examples provided in them. + +Code splitting is one of the most compelling features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel. It can be used to achieve smaller bundles and control resource load prioritization which, if used correctly, can have a major impact on load time. + +There are three general approaches to code splitting available: + +- Entry Points: Manually split code using [`entry`](/configuration/entry-context) configuration. +- Prevent Duplication: Use the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) to dedupe and split chunks. +- Dynamic Imports: Split code via inline function calls within modules. + + +## Entry Points + +This is by far the easiest, and most intuitive, way to split code. However, it is more manual and has some pitfalls we will go over. Let's take a look at how we might split another module from the main bundle: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- another-module.js +|- /node_modules +``` + +__another-module.js__ + +``` js +import _ from 'lodash'; + +console.log( + _.join(['Another', 'module', 'loaded!'], ' ') +); +``` + +__webpack.config.js__ + +``` diff +const path = require('path'); + +module.exports = { + mode: 'development', + entry: { + index: './src/index.js', ++ another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +This will yield the following build result: + +``` bash +... + Asset Size Chunks Chunk Names +another.bundle.js 550 KiB another [emitted] another + index.bundle.js 550 KiB index [emitted] index +Entrypoint index = index.bundle.js +Entrypoint another = another.bundle.js +... +``` + +As mentioned there are some pitfalls to this approach: + +- If there are any duplicated modules between entry chunks they will be included in both bundles. +- It isn't as flexible and can't be used to dynamically split code with the core application logic. + +The first of these two points is definitely an issue for our example, as `lodash` is also imported within `./src/index.js` and will thus be duplicated in both bundles. Let's remove this duplication by using the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). + + +## Prevent Duplication + +The [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) allows us to extract common dependencies into an existing entry chunk or an entirely new chunk. Let's use this to de-duplicate the `lodash` dependency from the previous example: + +W> The `CommonsChunkPlugin` has been removed in webpack v4 legato. To learn how chunks are treated in the latest version, check out the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + mode: 'development', + entry: { + index: './src/index.js', + another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ optimization: { ++ splitChunks: { ++ chunks: 'all' ++ } ++ } + }; +``` + +With the [`optimization.splitChunks`](/plugins/split-chunks-plugin/#optimization-splitchunks) configuration option in place, we should now see the duplicate dependency removed from our `index.bundle.js` and `another.bundle.js`. The plugin should notice that we've separated `lodash` out to a separate chunk and remove the dead weight from our main bundle. Let's do an `npm run build` to see if it worked: + +``` bash +... + Asset Size Chunks Chunk Names + another.bundle.js 5.95 KiB another [emitted] another + index.bundle.js 5.89 KiB index [emitted] index +vendors~another~index.bundle.js 547 KiB vendors~another~index [emitted] vendors~another~index +Entrypoint index = vendors~another~index.bundle.js index.bundle.js +Entrypoint another = vendors~another~index.bundle.js another.bundle.js +... +``` + +Here are some other useful plugins and loaders provided by the community for splitting code: + +- [`mini-css-extract-plugin`](/plugins/mini-css-extract-plugin): Useful for splitting CSS out from the main application. +- [`bundle-loader`](/loaders/bundle-loader): Used to split code and lazy load the resulting bundles. +- [`promise-loader`](https://github.com/gaearon/promise-loader): Similar to the `bundle-loader` but uses promises. + + +## Dynamic Imports + +Two similar techniques are supported by webpack when it comes to dynamic code splitting. The first and recommended approach is to use the [`import()` syntax](/api/module-methods#import-) that conforms to the [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) for dynamic imports. The legacy, webpack-specific approach is to use [`require.ensure`](/api/module-methods#require-ensure). Let's try using the first of these two approaches... + +W> `import()` calls use [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). + +Before we start, let's remove the extra [`entry`](/concepts/entry-points/) and [`optimization.splitChunks`](/plugins/split-chunks-plugin) from our config as they won't be needed for this next demonstration: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + mode: 'development', + entry: { ++ index: './src/index.js' +- index: './src/index.js', +- another: './src/another-module.js' + }, + output: { + filename: '[name].bundle.js', ++ chunkFilename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, +- optimization: { +- splitChunks: { +- chunks: 'all' +- } +- } + }; +``` + +Note the use of `chunkFilename`, which determines the name of non-entry chunk files. For more information on `chunkFilename`, see [output documentation](/configuration/output/#output-chunkfilename). We'll also update our project to remove the now unused files: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +- |- another-module.js +|- /node_modules +``` + +Now, instead of statically importing `lodash`, we'll use dynamic importing to separate a chunk: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; +- +- function component() { ++ function getComponent() { +- var element = document.createElement('div'); +- +- // Lodash, now imported by this script +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => { ++ var element = document.createElement('div'); ++ ++ element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ ++ return element; ++ ++ }).catch(error => 'An error occurred while loading the component'); + } + +- document.body.appendChild(component()); ++ getComponent().then(component => { ++ document.body.appendChild(component); ++ }) +``` + +The reason we need `default` is since webpack 4, when importing a CommonJS module, the import will no longer resolve to the value of `module.exports`, it will instead create an artificial namespace object for the CommonJS module, for more information on the reason behind this, read [webpack 4: import() and CommonJs](https://medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655) + +Note the use of `webpackChunkName` in the comment. This will cause our separate bundle to be named `lodash.bundle.js` instead of just `[id].bundle.js`. For more information on `webpackChunkName` and the other available options, see the [`import()` documentation](/api/module-methods#import-). Let's run webpack to see `lodash` separated out to a separate bundle: + +``` bash +... + Asset Size Chunks Chunk Names + index.bundle.js 7.88 KiB index [emitted] index +vendors~lodash.bundle.js 547 KiB vendors~lodash [emitted] vendors~lodash +Entrypoint index = index.bundle.js +... +``` + +As `import()` returns a promise, it can be used with [`async` functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). However, this requires using a pre-processor like Babel and the [Syntax Dynamic Import Babel Plugin](https://babeljs.io/docs/plugins/syntax-dynamic-import/#installation). Here's how it would simplify the code: + +__src/index.js__ + +``` diff +- function getComponent() { ++ async function getComponent() { +- return import(/* webpackChunkName: "lodash" */ 'lodash').then({ default: _ } => { +- var element = document.createElement('div'); +- +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- +- return element; +- +- }).catch(error => 'An error occurred while loading the component'); ++ var element = document.createElement('div'); ++ const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash'); ++ ++ element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ ++ return element; + } + + getComponent().then(component => { + document.body.appendChild(component); + }); +``` + + +## Prefetching/Preloading modules + +webpack 4.6.0+ adds support for prefetching and preloading. + +Using these inline directives while declaring your imports allows webpack to output “Resource Hint” which tells the browser that for: + +- prefetch: resource is probably needed for some navigation in the future +- preload: resource might be needed during the current navigation + +Simple prefetch example can be having a `HomePage` component, which renders a `LoginButton` component which then on demand loads a `LoginModal` component after being clicked. + +__LoginButton.js__ + +```js +//... +import(/* webpackPrefetch: true */ 'LoginModal'); +``` + +This will result in `<link rel="prefetch" href="login-modal-chunk.js">` being appended in the head of the page, which will instruct the browser to prefetch in idle time the `login-modal-chunk.js` file. + +T> webpack will add the prefetch hint once the parent chunk has been loaded. + +Preload directive has a bunch of differences compared to prefetch: + +- A preloaded chunk starts loading in parallel to the parent chunk. A prefetched chunk starts after the parent chunk finishes loading. +- A preloaded chunk has medium priority and is instantly downloaded. A prefetched chunk is downloaded while browser is idle. +- A preloaded chunk should be instantly requested by the parent chunk. A prefetched chunk can be used anytime in the future. +- Browser support is different. + +Simple preload example can be having a `Component` which always depends on a big library that should be in a separate chunk. + +Let's imagine a component `ChartComponent` which needs huge `ChartingLibrary`. It displays a `LoadingIndicator` when rendered and instantly does an on demand import of `ChartingLibrary`: + +__ChartComponent.js__ + +```js +//... +import(/* webpackPreload: true */ 'ChartingLibrary'); +``` + +When a page which uses the `ChartComponent` is requested, the charting-library-chunk is also requested via `<link rel="preload">`. Assuming the page-chunk is smaller and finishes faster, the page will be displayed with a `LoadingIndicator`, until the already requested `charting-library-chunk` finishes. This will give a little load time boost since it only needs one round-trip instead of two. Especially in high-latency environments. + +T> Using webpackPreload incorrectly can actually hurt performance, so be careful when using it. + + +## Bundle Analysis + +Once you start splitting your code, it can be useful to analyze the output to check where modules have ended up. The [official analyze tool](https://github.com/webpack/analyse) is a good place to start. There are some other community-supported options out there as well: + +- [webpack-chart](https://alexkuz.github.io/webpack-chart/): Interactive pie chart for webpack stats. +- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/): Visualize and analyze your bundles to see which modules are taking up space and which might be duplicates. +- [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer): A plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap. +- [webpack bundle optimize helper](https://webpack.jakoblind.no/optimize): This tool will analyze your bundle and give you actionable suggestions on what to improve to reduce your bundle size. + +## Next Steps + +See [Lazy Loading](/guides/lazy-loading) for a more concrete example of how `import()` can be used in a real application and [Caching](/guides/caching) to learn how to split code more effectively. + + +# Lazy Loading + +T> This guide is a small follow-up to [Code Splitting](/guides/code-splitting). If you have not yet read through that guide, please do so now. + +Lazy, or "on demand", loading is a great way to optimize your site or application. This practice essentially involves splitting your code at logical breakpoints, and then loading it once the user has done something that requires, or will require, a new block of code. This speeds up the initial load of the application and lightens its overall weight as some blocks may never even be loaded. + + +## Example + +Let's take the example from [Code Splitting](/guides/code-splitting#dynamic-imports) and tweak it a bit to demonstrate this concept even more. The code there does cause a separate chunk, `lodash.bundle.js`, to be generated and technically "lazy-loads" it as soon as the script is run. The trouble is that no user interaction is required to load the bundle -- meaning that every time the page is loaded, the request will fire. This doesn't help us too much and will impact performance negatively. + +Let's try something different. We'll add an interaction to log some text to the console when the user clicks a button. However, we'll wait to load that code (`print.js`) until the interaction occurs for the first time. To do this we'll go back and rework the [final _Dynamic Imports_ example](/guides/code-splitting#dynamic-imports) from _Code Splitting_ and leave `lodash` in the main chunk. + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- print.js +|- /node_modules +``` + +__src/print.js__ + +``` js +console.log('The print.js module has loaded! See the network tab in dev tools...'); + +export default () => { + console.log('Button Clicked: Here\'s "some text"!'); +}; +``` + +__src/index.js__ + +``` diff ++ import _ from 'lodash'; ++ +- async function getComponent() { ++ function component() { + var element = document.createElement('div'); +- const _ = await import(/* webpackChunkName: "lodash" */ 'lodash'); ++ var button = document.createElement('button'); ++ var br = document.createElement('br'); + ++ button.innerHTML = 'Click me and look at the console!'; + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.appendChild(br); ++ element.appendChild(button); ++ ++ // Note that because a network request is involved, some indication ++ // of loading would need to be shown in a production-level site/app. ++ button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => { ++ var print = module.default; ++ ++ print(); ++ }); + + return element; + } + +- getComponent().then(component => { +- document.body.appendChild(component); +- }); ++ document.body.appendChild(component()); +``` + +W> Note that when using `import()` on ES6 modules you must reference the `.default` property as it's the actual `module` object that will be returned when the promise is resolved. + +Now let's run webpack and check out our new lazy-loading functionality: + +``` bash +... + Asset Size Chunks Chunk Names +print.bundle.js 417 bytes 0 [emitted] print +index.bundle.js 548 kB 1 [emitted] [big] index + index.html 189 bytes [emitted] +... +``` + + +## Frameworks + +Many frameworks and libraries have their own recommendations on how this should be accomplished within their methodologies. Here are a few examples: + +- React: [Code Splitting and Lazy Loading](https://reacttraining.com/react-router/web/guides/code-splitting) +- Vue: [Lazy Load in Vue using Webpack's code splitting](https://alexjoverm.github.io/2017/07/16/Lazy-load-in-Vue-using-Webpack-s-code-splitting/) +- AngularJS: [AngularJS + Webpack = lazyLoad](https://medium.com/@var_bin/angularjs-webpack-lazyload-bb7977f390dd) by [@var_bincom](https://twitter.com/var_bincom) + + +# Caching + +T> The examples in this guide stem from [getting started](/guides/getting-started), [output management](/guides/output-management) and [code splitting](/guides/code-splitting). + +So we're using webpack to bundle our modular application which yields a deployable `/dist` directory. Once the contents of `/dist` have been deployed to a server, clients (typically browsers) will hit that server to grab the site and its assets. The last step can be time consuming, which is why browsers use a technique called [caching](https://searchstorage.techtarget.com/definition/cache). This allows sites to load faster with less unnecessary network traffic, however it can also cause headaches when you need new code to be picked up. + +This guide focuses on the configuration needed to ensure files produced by webpack compilation can remain cached unless their contents has changed. + + +## Output Filenames + +A simple way to ensure the browser picks up changed files is by using `output.filename` [substitutions](/configuration/output#output-filename). The `[hash]` substitution can be used to include a build-specific hash in the filename, however it's even better to use the `[contenthash]` substitution which is the hash of the content of a file, which is different for each asset. + +Let's get our project set up using the example from [getting started](/guides/getting-started) with the `plugins` from [output management](/guides/output-management), so we don't have to deal with maintaining our `index.html` file manually: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +|- /node_modules +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ +- title: 'Output Management' ++ title: 'Caching' + }) + ], + output: { +- filename: 'bundle.js', ++ filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +Running our build script, `npm run build`, with this configuration should produce the following output: + +``` bash +... + Asset Size Chunks Chunk Names +main.7e2c49a622975ebd9b7e.js 544 kB 0 [emitted] [big] main + index.html 197 bytes [emitted] +... +``` + +As you can see the bundle's name now reflects its content (via the hash). If we run another build without making any changes, we'd expect that filename to stay the same. However, if we were to run it again, we may find that this is not the case: + +``` bash +... + Asset Size Chunks Chunk Names +main.205199ab45963f6a62ec.js 544 kB 0 [emitted] [big] main + index.html 197 bytes [emitted] +... +``` + +This is because webpack includes certain boilerplate, specifically the runtime and manifest, in the entry chunk. + +W> Output may differ depending on your current webpack version. Newer versions may not have all the same issues with hashing as some older versions, but we still recommend the following steps to be safe. + +## Extracting Boilerplate + +As we learned in [code splitting](/guides/code-splitting), the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) can be used to split modules out into separate bundles. webpack provides an optimization feature which does split out runtime code into a separate chunk(s) according to the options provided, simply use [`optimization.runtimeChunk`](/configuration/optimization/#optimization-runtimechunk) set to `single` for creating one runtime bundle: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, ++ optimization: { ++ runtimeChunk: 'single' ++ } + }; +``` + +Let's run another build to see the extracted `runtime` bundle: + +``` bash +Hash: 82c9c385607b2150fab2 +Version: webpack 4.12.0 +Time: 3027ms + Asset Size Chunks Chunk Names +runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime + main.e81de2cf758ada72f306.js 69.5 KiB 1 [emitted] main + index.html 275 bytes [emitted] +[1] (webpack)/buildin/module.js 497 bytes {1} [built] +[2] (webpack)/buildin/global.js 489 bytes {1} [built] +[3] ./src/index.js 309 bytes {1} [built] + + 1 hidden module +``` + +It's also good practice to extract third-party libraries, such as `lodash` or `react`, to a separate `vendor` chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date. +This can be done by using the [`cacheGroups`](/plugins/split-chunks-plugin/#splitchunks-cachegroups) option of the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) demonstrated in [Example 2 of SplitChunksPlugin](/plugins/split-chunks-plugin/#split-chunks-example-2). Lets add `optimization.splitChunks` with `cacheGroups` with next params and build: + +__webpack.config.js__ + +``` diff + var path = require('path'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + }), + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, + optimization: { +- runtimeChunk: 'single' ++ runtimeChunk: 'single', ++ splitChunks: { ++ cacheGroups: { ++ vendor: { ++ test: /[\\/]node_modules[\\/]/, ++ name: 'vendors', ++ chunks: 'all' ++ } ++ } ++ } + } + }; +``` + +Let's run another build to see our new `vendor` bundle: + +``` bash +... + Asset Size Chunks Chunk Names +runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime +vendors.a42c3ca0d742766d7a28.js 69.4 KiB 1 [emitted] vendors + main.abf44fedb7d11d4312d7.js 240 bytes 2 [emitted] main + index.html 353 bytes [emitted] +... +``` + +We can now see that our `main` bundle does not contain `vendor` code from `node_modules` directory and is down in size to `240 bytes`! + +## Module Identifiers + +Let's add another module, `print.js`, to our project: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js ++ |- print.js +|- /node_modules +``` + +__print.js__ + +``` diff ++ export default function print(text) { ++ console.log(text); ++ }; +``` + +__src/index.js__ + +``` diff + import _ from 'lodash'; ++ import Print from './print'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.onclick = Print.bind(null, 'Hello webpack!'); + + return element; + } + + document.body.appendChild(component()); +``` + +Running another build, we would expect only our `main` bundle's hash to change, however... + +``` bash +... + Asset Size Chunks Chunk Names + vendor.a7561fb0e9a071baadb9.js 541 kB 0 [emitted] [big] vendor + main.b746e3eb72875af2caa9.js 1.22 kB 1 [emitted] main +manifest.1400d5af64fc1b7b3a45.js 5.85 kB 2 [emitted] manifest + index.html 352 bytes [emitted] +... +``` + +... we can see that all three have. This is because each [`module.id`](/api/module-variables#module-id-commonjs-) is incremented based on resolving order by default. Meaning when the order of resolving is changed, the IDs will be changed as well. So, to recap: + +- The `main` bundle changed because of its new content. +- The `vendor` bundle changed because its `module.id` was changed. +- And, the `manifest` bundle changed because it now contains a reference to a new module. + +The first and last are expected -- it's the `vendor` hash we want to fix. Luckily, there are two plugins we can use to resolve this issue. The first is the `NamedModulesPlugin`, which will use the path to the module rather than a numerical identifier. While this plugin is useful during development for more readable output, it does take a bit longer to run. The second option is the [`HashedModuleIdsPlugin`](/plugins/hashed-module-ids-plugin), which is recommended for production builds: + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const webpack = require('webpack'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + + module.exports = { + entry: './src/index.js', + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ + title: 'Caching' + }), ++ new webpack.HashedModuleIdsPlugin() + ], + output: { + filename: '[name].[contenthash].js', + path: path.resolve(__dirname, 'dist') + }, + optimization: { + runtimeChunk: 'single', + splitChunks: { + cacheGroups: { + vendor: { + test: /[\\/]node_modules[\\/]/, + name: 'vendors', + chunks: 'all' + } + } + } + } + }; +``` + +Now, despite any new local dependencies, our `vendor` hash should stay consistent between builds: + +``` bash +... + Asset Size Chunks Chunk Names + main.216e852f60c8829c2289.js 340 bytes 0 [emitted] main +vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors +runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime + index.html 353 bytes [emitted] +Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.216e852f60c8829c2289.js +... +``` + +And let's modify our `src/index.js` to temporarily remove that extra dependency: + +__src/index.js__ + +``` diff + import _ from 'lodash'; +- import Print from './print'; ++ // import Print from './print'; + + function component() { + var element = document.createElement('div'); + + // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); +- element.onclick = Print.bind(null, 'Hello webpack!'); ++ // element.onclick = Print.bind(null, 'Hello webpack!'); + + return element; + } + + document.body.appendChild(component()); +``` + +And finally run our build again: + +``` bash +... + Asset Size Chunks Chunk Names + main.ad717f2466ce655fff5c.js 274 bytes 0 [emitted] main +vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors +runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime + index.html 353 bytes [emitted] +Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.ad717f2466ce655fff5c.js +... +``` + +We can see that both builds yielded `55e79e5927a639d21a1b` in the `vendor` bundle's filename. + + +## Conclusion + +Caching gets messy. Plain and simple. However the walk-through above should give you a running start to deploying consistent, cacheable assets. See the _Further Reading_ section below to learn more. + + +# Authoring Libraries + +Aside from applications, webpack can also be used to bundle JavaScript libraries. The following guide is meant for library authors looking to streamline their bundling strategy. + + +## Authoring a Library + +Let's assume that you are writing a small library ,`webpack-numbers`, that allows users to convert the numbers 1 through 5 from their numeric representation to a textual one and vice-versa, e.g. 2 to 'two'. + +The basic project structure may look like this: + +__project__ + +``` diff ++ |- webpack.config.js ++ |- package.json ++ |- /src ++ |- index.js ++ |- ref.json +``` + +Initialize npm, install webpack and lodash: + +``` bash +npm init -y +npm install --save-dev webpack lodash +``` + +__src/ref.json__ + +```json +[ + { + "num": 1, + "word": "One" + }, + { + "num": 2, + "word": "Two" + }, + { + "num": 3, + "word": "Three" + }, + { + "num": 4, + "word": "Four" + }, + { + "num": 5, + "word": "Five" + }, + { + "num": 0, + "word": "Zero" + } +] +``` + +__src/index.js__ + +``` js +import _ from 'lodash'; +import numRef from './ref.json'; + +export function numToWord(num) { + return _.reduce(numRef, (accum, ref) => { + return ref.num === num ? ref.word : accum; + }, ''); +} + +export function wordToNum(word) { + return _.reduce(numRef, (accum, ref) => { + return ref.word === word && word.toLowerCase() ? ref.num : accum; + }, -1); +} +``` + +The usage specification for the library use will be as follows: + +- __ES2015 module import:__ + +``` js +import * as webpackNumbers from 'webpack-numbers'; +// ... +webpackNumbers.wordToNum('Two'); +``` + +- __CommonJS module require:__ + +``` js +var webpackNumbers = require('webpack-numbers'); +// ... +webpackNumbers.wordToNum('Two'); +``` + +- __AMD module require:__ + +``` js +require(['webpackNumbers'], function ( webpackNumbers) { + // ... + webpackNumbers.wordToNum('Two'); +}); +``` + +The consumer also can use the library by loading it via a script tag: + +``` html +<!doctype html> +<html> + ... + <script src="https://unpkg.com/webpack-numbers"></script> + <script> + // ... + // Global variable + webpackNumbers.wordToNum('Five') + // Property in the window object + window.webpackNumbers.wordToNum('Five') + // ... + </script> +</html> +``` + +Note that we can also configure it to expose the library in the following ways: + +- Property in the global object, for node. +- Property in the `this` object. + +For full library configuration and code please refer to [webpack-library-example](https://github.com/kalcifer/webpack-library-example). + + +## Base Configuration + +Now let's bundle this library in a way that will achieve the following goals: + +- Using `externals` to avoid bundling `lodash`, so the consumer is required to load it. +- Setting the library name as `webpack-numbers`. +- Exposing the library as a variable called `webpackNumbers`. +- Being able to access the library inside Node.js. + +Also, the consumer should be able to access the library the following ways: + +- ES2015 module. i.e. `import webpackNumbers from 'webpack-numbers'`. +- CommonJS module. i.e. `require('webpack-numbers')`. +- Global variable when included through `script` tag. + +We can start with this basic webpack configuration: + +__webpack.config.js__ + +``` js +var path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js' + } +}; +``` + + +## Externalize Lodash + +Now, if you run `webpack`, you will find that a largish bundle is created. If you inspect the file, you'll see that lodash has been bundled along with your code. In this case, we'd prefer to treat `lodash` as a `peerDependency`. Meaning that the consumer should already have `lodash` installed. Hence you would want to give up control of this external library to the consumer of your library. + +This can be done using the `externals` configuration: + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js' +- } ++ }, ++ externals: { ++ lodash: { ++ commonjs: 'lodash', ++ commonjs2: 'lodash', ++ amd: 'lodash', ++ root: '_' ++ } ++ } + }; +``` + +This means that your library expects a dependency named `lodash` to be available in the consumer's environment. + +T> Note that if you only plan on using your library as a dependency in another webpack bundle, you may specify `externals` as an array. + + +## External Limitations + +For libraries that use several files from a dependency: + +``` js +import A from 'library/one'; +import B from 'library/two'; + +// ... +``` + +You won't be able to exclude them from bundle by specifying `library` in the externals. You'll either need to exclude them one by one or by using a regular expression. + +``` js +module.exports = { + //... + externals: [ + 'library/one', + 'library/two', + // Everything that starts with "library/" + /^library\/.+$/ + ] +}; +``` + + +## Expose the Library + +For widespread use of the library, we would like it to be compatible in different environments, i.e. CommonJS, AMD, Node.js and as a global variable. To make your library available for consumption, add the `library` property inside `output`: + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), +- filename: 'webpack-numbers.js' ++ filename: 'webpack-numbers.js', ++ library: 'webpackNumbers' + }, + externals: { + lodash: { + commonjs: 'lodash', + commonjs2: 'lodash', + amd: 'lodash', + root: '_' + } + } + }; +``` + +T> Note that the `library` setup is tied to the `entry` configuration. For most libraries, specifying a single entry point is sufficient. While [multi-part libraries](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) are possible, it is simpler to expose partial exports through an [index script](https://stackoverflow.com/questions/34072598/es6-exporting-importing-in-index-file) that serves as a single entry point. Using an `array` as an `entry` point for a library is __not recommended__. + +This exposes your library bundle available as a global variable named `webpackNumbers` when imported. To make the library compatible with other environments, add `libraryTarget` property to the config. This will add the different options about how the library can be exposed. + +__webpack.config.js__ + +``` diff + var path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'webpack-numbers.js', +- library: 'webpackNumbers' ++ library: 'webpackNumbers', ++ libraryTarget: 'umd' + }, + externals: { + lodash: { + commonjs: 'lodash', + commonjs2: 'lodash', + amd: 'lodash', + root: '_' + } + } + }; +``` + +You can expose the library in the following ways: + +- Variable: as a global variable made available by a `script` tag (`libraryTarget:'var'`). +- This: available through the `this` object (`libraryTarget:'this'`). +- Window: available trough the `window` object, in the browser (`libraryTarget:'window'`). +- UMD: available after AMD or CommonJS `require` (`libraryTarget:'umd'`). + +If `library` is set and `libraryTarget` is not, `libraryTarget` defaults to `var` as specified in the [output configuration documentation](/configuration/output). See [`output.libraryTarget`](/configuration/output#output-librarytarget) there for a detailed list of all available options. + +W> With webpack 3.5.5, using `libraryTarget: { root:'_' }` doesn't work properly (as stated in [issue 4824](https://github.com/webpack/webpack/issues/4824)). However, you can set `libraryTarget: { var: '_' }` to expect the library as a global variable. + + +### Final Steps + +Optimize your output for production by following the steps in the [production guide](/guides/production). Let's also add the path to your generated bundle as the package's `main` field in with our `package.json` + +__package.json__ + +``` json +{ + ... + "main": "dist/webpack-numbers.js", + ... +} +``` + +Or, to add as standard module as per [this guide](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage): + +``` json +{ + ... + "module": "src/index.js", + ... +} +``` + +The key `main` refers to the [standard from `package.json`](https://docs.npmjs.com/files/package.json#main), and `module` to [a](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md) [proposal](https://github.com/rollup/rollup/wiki/pkg.module) to allow the JavaScript ecosystem upgrade to use ES2015 modules without breaking backwards compatibility. + +W> The `module` property should point to a script that utilizes ES2015 module syntax but no other syntax features that aren't yet supported by browsers or node. This enables webpack to parse the module syntax itself, allowing for lighter bundles via [tree shaking](https://webpack.js.org/guides/tree-shaking/) if users are only consuming certain parts of the library. + +Now you can [publish it as an npm package](https://docs.npmjs.com/getting-started/publishing-npm-packages) and find it at [unpkg.com](https://unpkg.com/#/) to distribute it to your users. + +T> To expose stylesheets associated with your library, the [`ExtractTextPlugin`](/plugins/extract-text-webpack-plugin) should be used. Users can then consume and load these as they would any other stylesheet. + + +# Shimming + +The `webpack` compiler can understand modules written as ES2015 modules, CommonJS or AMD. However, some third party libraries may expect global dependencies (e.g. `$` for `jQuery`). The libraries might also create globals which need to be exported. These "broken modules" are one instance where _shimming_ comes into play. + +W> __We don't recommend using globals!__ The whole concept behind webpack is to allow more modular front-end development. This means writing isolated modules that are well contained and do not rely on hidden dependencies (e.g. globals). Please use these features only when necessary. + +Another instance where _shimming_ can be useful is when you want to [polyfill](https://en.wikipedia.org/wiki/Polyfill) browser functionality to support more users. In this case, you may only want to deliver those polyfills to the browsers that need patching (i.e. load them on demand). + +The following article will walk through both of these use cases. + +T> For simplicity, this guide stems from the examples in [Getting Started](/guides/getting-started). Please make sure you are familiar with the setup there before moving on. + + +## Shimming Globals + +Let's start with the first use case of shimming global variables. Before we do anything let's take another look at our project: + +__project__ + +``` diff +webpack-demo +|- package.json +|- webpack.config.js +|- /dist +|- /src + |- index.js +|- /node_modules +``` + +Remember that `lodash` package we were using? For demonstration purposes, let's say we wanted to instead provide this as a global throughout our application. To do this, we can use the `ProvidePlugin`. + +The [`ProvidePlugin`](/plugins/provide-plugin) makes a package available as a variable in every module compiled through webpack. If webpack sees that variable used, it will include the given package in the final bundle. Let's go ahead by removing the `import` statement for `lodash` and instead providing it via the plugin: + +__src/index.js__ + +``` diff +- import _ from 'lodash'; +- + function component() { + var element = document.createElement('div'); + +- // Lodash, now imported by this script + element.innerHTML = _.join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); ++ const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') +- } ++ }, ++ plugins: [ ++ new webpack.ProvidePlugin({ ++ _: 'lodash' ++ }) ++ ] + }; +``` + +What we've essentially done here is tell webpack... + +> If you encounter at least one instance of the variable `_`, include the `lodash` package and provide it to the modules that need it. + +If we run a build, we should still see the same output: + +``` bash +... + Asset Size Chunks Chunk Names +bundle.js 544 kB 0 [emitted] [big] main +... +``` + +We can also use the `ProvidePlugin` to expose a single export of a module by configuring it with an "array path" (e.g. `[module, child, ...children?]`). So let's imagine we only wanted to provide the `join` method from `lodash` wherever it's invoked: + +__src/index.js__ + +``` diff + function component() { + var element = document.createElement('div'); + +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + plugins: [ + new webpack.ProvidePlugin({ +- _: 'lodash' ++ join: ['lodash', 'join'] + }) + ] + }; +``` + +This would go nicely with [Tree Shaking](/guides/tree-shaking) as the rest of the `lodash` library should get dropped. + + +## Granular Shimming + +Some legacy modules rely on `this` being the `window` object. Let's update our `index.js` so this is the case: + +``` diff + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); ++ ++ // Assume we are in the context of `window` ++ this.alert('Hmmm, this probably isn\'t a great idea...') + + return element; + } + + document.body.appendChild(component()); +``` + +This becomes a problem when the module is executed in a CommonJS context where `this` is equal to `module.exports`. In this case you can override `this` using the [`imports-loader`](/loaders/imports-loader/): + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, ++ module: { ++ rules: [ ++ { ++ test: require.resolve('index.js'), ++ use: 'imports-loader?this=>window' ++ } ++ ] ++ }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + + +## Global Exports + +Let's say a library creates a global variable that it expects its consumers to use. We can add a small module to our setup to demonstrate this: + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js ++ |- globals.js + |- /node_modules +``` + +__src/globals.js__ + +``` js +var file = 'blah.txt'; +var helpers = { + test: function() { console.log('test something'); }, + parse: function() { console.log('parse something'); } +}; +``` + +Now, while you'd likely never do this in your own source code, you may encounter a dated library you'd like to use that contains similar code to what's shown above. In this case, we can use [`exports-loader`](/loaders/exports-loader/), to export that global variable as a normal module export. For instance, in order to export `file` as `file` and `helpers.parse` as `parse`: + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: require.resolve('index.js'), + use: 'imports-loader?this=>window' +- } ++ }, ++ { ++ test: require.resolve('globals.js'), ++ use: 'exports-loader?file,parse=helpers.parse' ++ } + ] + }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + +Now from within our entry script (i.e. `src/index.js`), we could `import { file, parse } from './globals.js';` and all should work smoothly. + + +## Loading Polyfills + +Almost everything we've discussed thus far has been in relation to handling legacy packages. Let's move on to our second topic: __polyfills__. + +There's a lot of ways to load polyfills. For example, to include the [`babel-polyfill`](https://babeljs.io/docs/usage/polyfill/) we might simply: + +``` bash +npm install --save babel-polyfill +``` + +and `import` it so as to include it in our main bundle: + +__src/index.js__ + +``` diff ++ import 'babel-polyfill'; ++ + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +T> Note that we aren't binding the `import` to a variable. This is because polyfills simply run on their own, prior to the rest of the code base, allowing us to then assume certain native functionality exists. + +Now while this is one approach, __including polyfills in the main bundle is not recommended__ because this penalizes modern browsers users by making them download a bigger file with unneeded scripts. + +Let's move our `import` to a new file and add the [`whatwg-fetch`](https://github.com/github/fetch) polyfill: + +``` bash +npm install --save whatwg-fetch +``` + +__src/index.js__ + +``` diff +- import 'babel-polyfill'; +- + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); +``` + +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js + |- globals.js ++ |- polyfills.js + |- /node_modules +``` + +__src/polyfills.js__ + +```javascript +import 'babel-polyfill'; +import 'whatwg-fetch'; +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const webpack = require('webpack'); + + module.exports = { +- entry: './src/index.js', ++ entry: { ++ polyfills: './src/polyfills.js', ++ index: './src/index.js' ++ }, + output: { +- filename: 'bundle.js', ++ filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + }, + module: { + rules: [ + { + test: require.resolve('index.js'), + use: 'imports-loader?this=>window' + }, + { + test: require.resolve('globals.js'), + use: 'exports-loader?file,parse=helpers.parse' + } + ] + }, + plugins: [ + new webpack.ProvidePlugin({ + join: ['lodash', 'join'] + }) + ] + }; +``` + +With that in place, we can add the logic to conditionally load our new `polyfills.bundle.js` file. How you make this decision depends on the technologies and browsers you need to support. We'll just do some simple testing to determine whether our polyfills are needed: + +__dist/index.html__ + +``` diff + <!doctype html> + <html> + <head> + <title>Getting Started</title> ++ <script> ++ var modernBrowser = ( ++ 'fetch' in window && ++ 'assign' in Object ++ ); ++ ++ if ( !modernBrowser ) { ++ var scriptElement = document.createElement('script'); ++ ++ scriptElement.async = false; ++ scriptElement.src = '/polyfills.bundle.js'; ++ document.head.appendChild(scriptElement); ++ } ++ </script> + </head> + <body> + <script src="index.bundle.js"></script> + </body> + </html> +``` + +Now we can `fetch` some data within our entry script: + +__src/index.js__ + +``` diff + function component() { + var element = document.createElement('div'); + + element.innerHTML = join(['Hello', 'webpack'], ' '); + + return element; + } + + document.body.appendChild(component()); ++ ++ fetch('https://jsonplaceholder.typicode.com/users') ++ .then(response => response.json()) ++ .then(json => { ++ console.log('We retrieved some data! AND we\'re confident it will work on a variety of browser distributions.') ++ console.log(json) ++ }) ++ .catch(error => console.error('Something went wrong when fetching this data: ', error)) +``` + +If we run our build, another `polyfills.bundle.js` file will be emitted and everything should still run smoothly in the browser. Note that this set up could likely be improved upon but it should give you a good idea of how you can provide polyfills only to the users that actually need them. + + +## Further Optimizations + +The `babel-preset-env` package uses [browserslist](https://github.com/browserslist/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the [`useBuiltIns`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins) option, `false` by default, which converts your global `babel-polyfill` import to a more granular feature by feature `import` pattern: + +``` js +import 'core-js/modules/es7.string.pad-start'; +import 'core-js/modules/es7.string.pad-end'; +import 'core-js/modules/web.timers'; +import 'core-js/modules/web.immediate'; +import 'core-js/modules/web.dom.iterable'; +``` + +See [the repository](https://github.com/babel/babel-preset-env) for more information. + + +## Node Built-Ins + +Node built-ins, like `process`, can be polyfilled right directly from your configuration file without the use of any special loaders or plugins. See the [node configuration page](/configuration/node) for more information and examples. + + +## Other Utilities + +There are a few other tools that can help when dealing with legacy modules. + +The [`script-loader`](/loaders/script-loader/) evaluates code in the global context, similar to inclusion via a `script` tag. In this mode, every normal library should work. `require`, `module`, etc. are undefined. + +W> When using the `script-loader`, the module is added as a string to the bundle. It is not minimized by `webpack`, so use a minimized version. There is also no `devtool` support for libraries added by this loader. + +When there is no AMD/CommonJS version of the module and you want to include the `dist`, you can flag this module in [`noParse`](/configuration/module/#module-noparse). This will cause webpack to include the module without parsing it or resolving `require()` and `import` statements. This practice is also used to improve the build performance. + +W> Any feature requiring the AST, like the `ProvidePlugin`, will not work. + +Lastly, there are some modules that support multiple [module styles](/concepts/modules); e.g. a combination of AMD, CommonJS, and legacy. In most of these cases, they first check for `define` and then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by setting `define=>false` via the [`imports-loader`](/loaders/imports-loader/). + + +# Progressive Web Application + +T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. + +Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications. There are many things that can contribute to that. Of these, the most significant is the ability for an app to be able to function when __offline__. This is achieved through the use of a web technology called [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers/). + +This section will focus on adding an offline experience to our app. We'll achieve this using a Google project called [Workbox](https://github.com/GoogleChrome/workbox) which provides tools that help make offline support for web apps easier to setup. + + +## We Don't Work Offline Now + +So far, we've been viewing the output by going directly to the local file system. Typically though, a real user accesses a web app over a network; their browser talking to a __server__ which will serve up the required assets (e.g. `.html`, `.js`, and `.css` files). + +So let's test what the current experience is like using a simple server. Let's use the [http-server](https://www.npmjs.com/package/http-server) package: `npm install http-server --save-dev`. We'll also amend the `scripts` section of our `package.json` to add in a `start` script: + +__package.json__ + +``` diff +{ + ... + "scripts": { +- "build": "webpack" ++ "build": "webpack", ++ "start": "http-server dist" + }, + ... +} +``` + +If you haven't previously done so, run the command `npm run build` to build your project. Then run the command `npm start`. This should produce the following output: + +``` bash +> http-server dist + +Starting up http-server, serving dist +Available on: + http://xx.x.x.x:8080 + http://127.0.0.1:8080 + http://xxx.xxx.x.x:8080 +Hit CTRL-C to stop the server +``` + +If you open your browser to `http://localhost:8080` (i.e. `http://127.0.0.1`) you should see your webpack application being served from the `dist` directory. If you stop the server and refresh, the webpack application is no longer available. + +This is what we aim to change. Once we reach the end of this module we should be able to stop the server, hit refresh and still see our application. + + +## Adding Workbox + +Let's add the Workbox webpack plugin and adjust the `webpack.config.js` file: + +``` bash +npm install workbox-webpack-plugin --save-dev +``` + +__webpack.config.js__ + +``` diff + const path = require('path'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); ++ const WorkboxPlugin = require('workbox-webpack-plugin'); + + module.exports = { + entry: { + app: './src/index.js', + print: './src/print.js' + }, + plugins: [ + new CleanWebpackPlugin(['dist']), + new HtmlWebpackPlugin({ +- title: 'Output Management' ++ title: 'Progressive Web Application' +- }) ++ }), ++ new WorkboxPlugin.GenerateSW({ ++ // these options encourage the ServiceWorkers to get in there fast ++ // and not allow any straggling "old" SWs to hang around ++ clientsClaim: true, ++ skipWaiting: true ++ }) + ], + output: { + filename: '[name].bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +With that in place, let's see what happens when we do an `npm run build`: + +``` bash +... + Asset Size Chunks Chunk Names + app.bundle.js 545 kB 0, 1 [emitted] [big] app + print.bundle.js 2.74 kB 1 [emitted] print + index.html 254 bytes [emitted] +precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 268 bytes [emitted] + service-worker.js 1 kB [emitted] +... +``` + +As you can see, we now have 2 extra files being generated; `service-worker.js` and the more verbose `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js`. `service-worker.js` is the Service Worker file and `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js` is a file that `service-worker.js` requires so it can run. Your own generated files will likely be different; but you should have an `service-worker.js` file there. + +So we're now at the happy point of having produced a Service Worker. What's next? + + +## Registering Our Service Worker + +Let's allow our Service Worker to come out and play by registering it. We'll do that by adding the registration code below: + +__index.js__ + +``` diff + import _ from 'lodash'; + import printMe from './print.js'; + ++ if ('serviceWorker' in navigator) { ++ window.addEventListener('load', () => { ++ navigator.serviceWorker.register('/service-worker.js').then(registration => { ++ console.log('SW registered: ', registration); ++ }).catch(registrationError => { ++ console.log('SW registration failed: ', registrationError); ++ }); ++ }); ++ } +``` + +Once more `npm run build` to build a version of the app including the registration code. Then serve it with `npm start`. Navigate to `http://localhost:8080` and take a look at the console. Somewhere in there you should see: + +``` bash +SW registered +``` + +Now to test it. Stop your server and refresh your page. If your browser supports Service Workers then you should still be looking at your application. However, it has been served up by your Service Worker and __not__ by the server. + + +## Conclusion + +You have built an offline app using the Workbox project. You've started the journey of turning your web app into a PWA. You may now want to think about taking things further. A good resource to help you with that can be found [here](https://developers.google.com/web/progressive-web-apps/). + + +# TypeScript + +T> This guide stems from the [_Getting Started_](/guides/getting-started/) guide. + +[TypeScript](https://www.typescriptlang.org) is a typed superset of JavaScript that compiles to plain JavaScript. In this guide we will learn how to integrate TypeScript with webpack. + + +## Basic Setup + +First install the TypeScript compiler and loader by running: + +``` bash +npm install --save-dev typescript ts-loader +``` + +Now we'll modify the directory structure & the configuration files: + +__project__ + +``` diff + webpack-demo + |- package.json ++ |- tsconfig.json + |- webpack.config.js + |- /dist + |- bundle.js + |- index.html + |- /src + |- index.js ++ |- index.ts + |- /node_modules +``` + +__tsconfig.json__ + +Let's set up a simple configuration to support JSX and compile TypeScript down to ES5... + +``` json +{ + "compilerOptions": { + "outDir": "./dist/", + "noImplicitAny": true, + "module": "es6", + "target": "es5", + "jsx": "react", + "allowJs": true + } +} +``` + +See [TypeScript's documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) to learn more about `tsconfig.json` configuration options. + +To learn more about webpack configuration, see the [configuration concepts](/concepts/configuration/). + +Now let's configure webpack to handle TypeScript: + +__webpack.config.js__ + +``` js +const path = require('path'); + +module.exports = { + entry: './src/index.ts', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [ '.tsx', '.ts', '.js' ] + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } +}; +``` + +This will direct webpack to _enter_ through `./index.ts`, _load_ all `.ts` and `.tsx` files through the `ts-loader`, and _output_ a `bundle.js` file in our current directory. + + +## Loader + +[`ts-loader`](https://github.com/TypeStrong/ts-loader) + +We use `ts-loader` in this guide as it makes enabling additional webpack features, such as importing other web assets, a bit easier. + + +## Source Maps + +To learn more about source maps, see the [development guide](/guides/development). + +To enable source maps, we must configure TypeScript to output inline source maps to our compiled JavaScript files. The following line must be added to our TypeScript configuration: + +__tsconfig.json__ + +``` diff + { + "compilerOptions": { + "outDir": "./dist/", ++ "sourceMap": true, + "noImplicitAny": true, + "module": "commonjs", + "target": "es5", + "jsx": "react", + "allowJs": true + } + } +``` + +Now we need to tell webpack to extract these source maps and include in our final bundle: + +__webpack.config.js__ + +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.ts', ++ devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [ '.tsx', '.ts', '.js' ] + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +``` + +See the [devtool documentation](/configuration/devtool/) for more information. + + +## Using Third Party Libraries + +When installing third party libraries from npm, it is important to remember to install the typing definition for that library. These definitions can be found at [TypeSearch](http://microsoft.github.io/TypeSearch/). + +For example if we want to install lodash we can run the following command to get the typings for it: + +``` bash +npm install --save-dev @types/lodash +``` + +For more information see [this blog post](https://blogs.msdn.microsoft.com/typescript/2016/06/15/the-future-of-declaration-files/). + + +## Importing Other Assets + +To use non-code assets with TypeScript, we need to defer the type for these imports. This requires a `custom.d.ts` file which signifies custom definitions for TypeScript in our project. Let's set up a declaration for `.svg` files: + +__custom.d.ts__ + +```typescript +declare module "*.svg" { + const content: any; + export default content; +} +``` + +Here we declare a new module for SVGs by specifying any import that ends in `.svg` and defining the module's `content` as `any`. We could be more explicit about it being a url by defining the type as string. The same concept applies to other assets including CSS, SCSS, JSON and more. + + +## Build Performance + +W> This may degrade build performance. + +See the [Build Performance](/guides/build-performance/) guide on build tooling. + + +# Environment Variables + +To disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production) you may use environment variables. + +The webpack command line [environment option](/api/cli/#environment-options) `--env` allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your `webpack.config.js`. For example, `--env.production` or `--env.NODE_ENV=local` (`NODE_ENV` is conventionally used to define the environment type, see [here](https://dzone.com/articles/what-you-should-know-about-node-env).) + +```bash +webpack --env.NODE_ENV=local --env.production --progress +``` + +T> Setting up your `env` variable without assignment, `--env.production` sets `--env.production` to `true` by default. There are also other syntaxes that you can use. See the [webpack CLI](/api/cli/#environment-options) documentation for more information. + +There is one change that you will have to make to your webpack config. Typically, `module.exports` points to the configuration object. To use the `env` variable, you must convert `module.exports` to a function: + +__webpack.config.js__ + +``` js +const path = require('path'); + +module.exports = env => { + // Use env.<YOUR VARIABLE> here: + console.log('NODE_ENV: ', env.NODE_ENV); // 'local' + console.log('Production: ', env.production); // true + + return { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } + }; +}; +``` + + +# Build Performance + +This guide contains some useful tips for improving build/compilation performance. + +--- + +## General + +The following best practices should help, whether you're running build scripts in [development](/guides/development) or [production](/guides/production). + + +### Stay Up to Date + +Use the latest webpack version. We are always making performance improvements. The latest stable version of webpack is: + +[](https://github.com/webpack/webpack/releases) + +Staying up-to-date with __Node.js__ can also help with performance. On top of this, keeping your package manager (e.g. `npm` or `yarn`) up-to-date can also help. Newer versions create more efficient module trees and increase resolving speed. + + +### Loaders + +Apply loaders to the minimal number of modules necessary. Instead of: + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + loader: 'babel-loader' + } + ] + } +}; +``` + +Use the `include` field to only apply the loader modules that actually need to be transformed by it: + +```js +module.exports = { + //... + module: { + rules: [ + { + test: /\.js$/, + include: path.resolve(__dirname, 'src'), + loader: 'babel-loader' + } + ] + } +}; +``` + + +### Bootstrap + +Each additional loader/plugin has a bootup time. Try to use as few tools as possible. + + +### Resolving + +The following steps can increase resolving speed: + +- Minimize the number of items in `resolve.modules`, `resolve.extensions`, `resolve.mainFiles`, `resolve.descriptionFiles`, as they increase the number of filesystem calls. +- Set `resolve.symlinks: false` if you don't use symlinks (e.g. `npm link` or `yarn link`). +- Set `resolve.cacheWithContext: false` if you use custom resolving plugins, that are not context specific. + + +### Dlls + +Use the `DllPlugin` to move code that is changed less often into a separate compilation. This will improve the application's compilation speed, although it does increase complexity of the build process. + + +### Smaller = Faster + +Decrease the total size of the compilation to increase build performance. Try to keep chunks small. + +- Use fewer/smaller libraries. +- Use the `CommonsChunkPlugin` in Multi-Page Applications. +- Use the `CommonsChunkPlugin` in `async` mode in Multi-Page Applications. +- Remove unused code. +- Only compile the part of the code you are currently developing on. + + +### Worker Pool + +The `thread-loader` can be used to offload expensive loaders to a worker pool. + +W> Don't use too many workers, as there is a boot overhead for the Node.js runtime and the loader. Minimize the module transfers between worker and main process. IPC is expensive. + + +### Persistent cache + +Enable persistent caching with the `cache-loader`. Clear cache directory on `"postinstall"` in `package.json`. + + +### Custom plugins/loaders + +Profile them to not introduce a performance problem here. + +--- + + +## Development + +The following steps are especially useful in _development_. + + +### Incremental Builds + +Use webpack's watch mode. Don't use other tools to watch your files and invoke webpack. The built-in watch mode will keep track of timestamps and passes this information to the compilation for cache invalidation. + +In some setups, watching falls back to polling mode. With many watched files, this can cause a lot of CPU load. In these cases, you can increase the polling interval with `watchOptions.poll`. + + +### Compile in Memory + +The following utilities improve performance by compiling and serving assets in memory rather than writing to disk: + +- `webpack-dev-server` +- `webpack-hot-middleware` +- `webpack-dev-middleware` + +### stats.toJson speed + +webpack 4 outputs a large amount of data with its `stats.toJson()` by default. Avoid retrieving portions of the `stats` object unless necessary in the incremental step. `webpack-dev-server` after v3.1.3 contained a substantial performance fix to minimize the amount of data retrieved from the `stats` object per incremental build step. + +### Devtool + +Be aware of the performance differences of the different `devtool` settings. + +- `"eval"` has the best performance, but doesn't assist you for transpiled code. +- The `cheap-source-map` variants are more performant, if you can live with the slightly worse mapping quality. +- Use a `eval-source-map` variant for incremental builds. + +=> In most cases, `cheap-module-eval-source-map` is the best option. + + +### Avoid Production Specific Tooling + +Certain utilities, plugins, and loaders only make sense when building for production. For example, it usually doesn't make sense to minify and mangle your code with the `TerserPlugin` while in development. These tools should typically be excluded in development: + +- `TerserPlugin` +- `ExtractTextPlugin` +- `[hash]`/`[chunkhash]` +- `AggressiveSplittingPlugin` +- `AggressiveMergingPlugin` +- `ModuleConcatenationPlugin` + + +### Minimal Entry Chunk + +webpack only emits updated chunks to the filesystem. For some configuration options, (HMR, `[name]`/`[chunkhash]` in `output.chunkFilename`, `[hash]`) the entry chunk is invalidated in addition to the changed chunks. + +Make sure the entry chunk is cheap to emit by keeping it small. The following code block extracts a chunk containing only the runtime with _all other chunks as children_: + +```js +new CommonsChunkPlugin({ + name: 'manifest', + minChunks: Infinity +}); +``` + +### Avoid Extra Optimization Steps + +webpack does extra algorithmic work to optimize the output for size and load performance. These optimizations are performant for smaller codebases, but can be costly in larger ones: + +```js +module.exports = { + // ... + optimization: { + removeAvailableModules: false, + removeEmptyChunks: false, + splitChunks: false, + } +}; +``` + +### Output Without Path Info + +webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Turn this off in the `options.output.pathinfo` setting: + +```js +module.exports = { + // ... + output: { + pathinfo: false + } +}; +``` + +### Node.js Version + +There has been a [performance regression](https://github.com/nodejs/node/issues/19769) in the latest stable versions of Node.js and its ES2015 `Map` and `Set` implementations. A fix has been merged into master, but a release has yet to be made. In the meantime, to get the most out of incremental build speeds, try to stick with version 8.9.x (the problem exists between 8.9.10 - 9.11.1). webpack has moved to using those ES2015 data structures liberally, and it will improve the initial build times as well. + +### TypeScript Loader + +Recently, `ts-loader` has started to consume the internal TypeScript watch mode APIs which dramatically decreases the number of modules to be rebuilt on each iteration. This `experimentalWatchApi` shares the same logic as the normal TypeScript watch mode itself and is quite stable for development use. Turn on `transpileOnly`, as well, for even faster incremental builds. + +```js +module.exports = { + // ... + test: /\.tsx?$/, + use: [ + { + loader: 'ts-loader', + options: { + transpileOnly: true, + experimentalWatchApi: true, + }, + }, + ], +}; +``` + +Note: the `ts-loader` documentation suggests the use of `cache-loader`, but this actually slows the incremental builds down with disk writes. + +To gain typechecking again, use the [`ForkTsCheckerWebpackPlugin`](https://www.npmjs.com/package/fork-ts-checker-webpack-plugin). + +There is a [full example](https://github.com/TypeStrong/ts-loader/tree/master/examples/fast-incremental-builds) on the ts-loader github repository. + +--- + + +## Production + +The following steps are especially useful in _production_. + +W> __Don't sacrifice the quality of your application for small performance gains!__ Keep in mind that optimization quality is, in most cases, more important than build performance. + + +### Multiple Compilations + +When using multiple compilations, the following tools can help: + +- [`parallel-webpack`](https://github.com/trivago/parallel-webpack): It allows for compilation in a worker pool. +- `cache-loader`: The cache can be shared between multiple compilations. + + +### Source Maps + +Source maps are really expensive. Do you really need them? + +--- + + +## Specific Tooling Issues + +The following tools have certain problems that can degrade build performance: + + +### Babel + +- Minimize the number of preset/plugins + + +### TypeScript + +- Use the `fork-ts-checker-webpack-plugin` for typechecking in a separate process. +- Configure loaders to skip typechecking. +- Use the `ts-loader` in `happyPackMode: true` / `transpileOnly: true`. + + +### Sass + +- `node-sass` has a bug which blocks threads from the Node.js thread pool. When using it with the `thread-loader` set `workerParallelJobs: 2`. + + +# Content Security Policies + +Webpack is capable of adding `nonce` to all scripts that it loads. To activate the feature set a `__webpack_nonce__` variable needs to be included in your entry script. A unique hash based nonce should be generated and provided for each unique page view this is why `__webpack_nonce__` is specified in the entry file and not in the configuration. Please note that `nonce` should always be a base64-encoded string. + + +## Examples + +In the entry file: + +``` js +// ... +__webpack_nonce__ = 'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM='; +// ... +``` + + +## Enabling CSP + +Please note that CSPs are not enabled by default. A corresponding header `Content-Security-Policy` or meta tag `<meta http-equiv="Content-Security-Policy" ...>` needs to be sent with the document to instruct the browser to enable the CSP. Here's an example of what a CSP header including a CDN white-listed URL might look like: + +``` http +Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; +``` + +For more information on CSP and `nonce` attribute, please refer to __Further Reading__ section at the bottom of this page. + + +# Development - Vagrant + +If you have a more advanced project and use [Vagrant](https://www.vagrantup.com/) to run your development environment in a Virtual Machine, you'll often want to also run webpack in the VM. + +## Configuring the Project + +To start, make sure that the `Vagrantfile` has a static IP; + +```ruby +Vagrant.configure("2") do |config| + config.vm.network :private_network, ip: "10.10.10.61" +end +``` + +Next, install webpack and webpack-dev-server in your project; + +```bash +npm install --save-dev webpack webpack-dev-server +``` + +Make sure to have a `webpack.config.js` file. If you haven't already, use this as a minimal example to get started: + +```js +module.exports = { + context: __dirname, + entry: './app.js' +}; +``` + +And create a `index.html` file. The script tag should point to your bundle. If `output.filename` is not specified in the config, this will be `bundle.js`. + +```html +<!doctype html> +<html> + <head> + <script src="/bundle.js" charset="utf-8"></script> + </head> + <body> + <h2>Heey!</h2> + </body> +</html> +``` + +Note that you also need to create an `app.js` file. + +## Running the Server + +Now, let's run the server: + +```bash +webpack-dev-server --host 0.0.0.0 --public 10.10.10.61:8080 --watch-poll +``` + +By default the server will only be accessible from localhost. We'll be accessing it from our host PC, so we need to change `--host` to allow this. + +webpack-dev-server will include a script in your bundle that connects to a WebSocket to reload when a change in any of your files occurs. +The `--public` flag makes sure the script knows where to look for the WebSocket. The server will use port `8080` by default, so we should also specify that here. + +`--watch-poll` makes sure that webpack can detect changes in your files. By default webpack listens to events triggered by the filesystem, but VirtualBox has many problems with this. + +The server should be accessible on `http://10.10.10.61:8080` now. If you make a change in `app.js`, it should live reload. + +## Advanced Usage with nginx + +To mimic a more production-like environment, it is also possible to proxy the webpack-dev-server with nginx. + +In your nginx config file, add the following: + +```nginx +server { + location / { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + error_page 502 @start-webpack-dev-server; + } + + location @start-webpack-dev-server { + default_type text/plain; + return 502 "Please start the webpack-dev-server first."; + } +} +``` + +The `proxy_set_header` lines are important, because they allow the WebSockets to work correctly. + +The command to start webpack-dev-server can then be changed to this: + +```bash +webpack-dev-server --public 10.10.10.61 --watch-poll +``` + +This makes the server only accessible on `127.0.0.1`, which is fine, because nginx takes care of making it available on your host PC. + +## Conclusion + +We made the Vagrant box accessible from a static IP, and then made webpack-dev-server publicly accessible so it is reachable from a browser. We then tackled a common problem that VirtualBox doesn't send out filesystem events, causing the server to not reload on file changes. + + +# Dependency Management + +> es6 modules + +> commonjs + +> amd + + +## require with expression + +A context is created if your request contains expressions, so the __exact__ module is not known on compile time. + +Example: + +```javascript +require('./template/' + name + '.ejs'); +``` + +webpack parses the `require()` call and extracts some information: + +```code +Directory: ./template +Regular expression: /^.*\.ejs$/ +``` + +__context module__ + +A context module is generated. It contains references to __all modules in that directory__ that can be required with a request matching the regular expression. The context module contains a map which translates requests to module ids. + +Example: + +```json +{ + "./table.ejs": 42, + "./table-row.ejs": 43, + "./directory/folder.ejs": 44 +} +``` + +The context module also contains some runtime logic to access the map. + +This means dynamic requires are supported but will cause all possible modules to be included in the bundle. + + +## `require.context` + +You can create your own context with the `require.context()` function. + +It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched +too, and a regular expression to match files against. + +webpack parses for `require.context()` in the code while building. + +The syntax is as follows: + +```javascript +require.context(directory, useSubdirectories = false, regExp = /^\.\//); +``` + +Examples: + +```javascript +require.context('./test', false, /\.test\.js$/); +// a context with files from the test directory that can be required with a request endings with `.test.js`. +``` + +```javascript +require.context('../', true, /\.stories\.js$/); +// a context with all files in the parent folder and descending folders ending with `.stories.js`. +``` + +W> The arguments passed to `require.context` must be literals! + + +### context module API + +A context module exports a (require) function that takes one argument: the request. + +The exported function has 3 properties: `resolve`, `keys`, `id`. + +- `resolve` is a function and returns the module id of the parsed request. +- `keys` is a function that returns an array of all possible requests that the context module can handle. + +This can be useful if you want to require all files in a directory or matching a pattern, Example: + +```javascript +function importAll (r) { + r.keys().forEach(r); +} + +importAll(require.context('../components/', true, /\.js$/)); +``` + +```javascript +var cache = {}; + +function importAll (r) { + r.keys().forEach(key => cache[key] = r(key)); +} + +importAll(require.context('../components/', true, /\.js$/)); +// At build-time cache will be populated with all required modules. +``` + +- `id` is the module id of the context module. This may be useful for `module.hot.accept`. + + +# Public Path + +The `publicPath` configuration option can be quite useful in a variety of scenarios. It allows you to specify the base path for all the assets within your application. + + +## Use Cases + +There are a few use cases in real applications where this feature becomes especially neat. Essentially, every file emitted to your `output.path` directory will be referenced from the `output.publicPath` location. This includes child chunks (created via [code splitting](/guides/code-splitting/)) and any other assets (e.g. images, fonts, etc.) that are a part of your dependency graph. + +### Environment Based + +In development for example, we might have an `assets/` folder that lives on the same level of our index page. This is fine, but what if we wanted to host all these static assets on a CDN in production? + +To approach this problem you can easily use a good old environment variable. Let's say we have a variable `ASSET_PATH`: + +``` js +import webpack from 'webpack'; + +// Try the environment variable, otherwise use root +const ASSET_PATH = process.env.ASSET_PATH || '/'; + +export default { + output: { + publicPath: ASSET_PATH + }, + + plugins: [ + // This makes it possible for us to safely use env vars on our code + new webpack.DefinePlugin({ + 'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH) + }) + ] +}; +``` + +### On The Fly + +Another possible use case is to set the `publicPath` on the fly. webpack exposes a global variable called `__webpack_public_path__` that allows you to do that. So, in your application's entry point, you can simply do this: + +```js +__webpack_public_path__ = process.env.ASSET_PATH; +``` + +That's all you need. Since we're already using the `DefinePlugin` on our +configuration, `process.env.ASSET_PATH` will always be defined so we can safely +do that. + +W> Be aware that if you use ES6 module imports in your entry file the `__webpack_public_path__` assignment will be done after the imports. In such cases, you'll have to move the public path assignment to its own dedicated module and then import it on top of your entry.js: + +```js +// entry.js +import './public-path'; +import './app'; +``` + + +# Integrations + +Let's start by clearing up a common misconception. webpack is a module bundler like [Browserify](http://browserify.org/) or [Brunch](http://brunch.io/). It is _not a task runner_ like [Make](https://www.gnu.org/software/make/), [Grunt](https://gruntjs.com/), or [Gulp](https://gulpjs.com/). Task runners handle automation of common development tasks such as linting, building, or testing your project. Compared to bundlers, task runners have a higher level focus. You can still benefit from their higher level tooling while leaving the problem of bundling to webpack. + +Bundlers help you get your JavaScript and stylesheets ready for deployment, transforming them into a format that's suitable for the browser. For example, JavaScript can be [minified](/plugins/terser-webpack-plugin) or [split into chunks](/guides/code-splitting) and [lazy-loaded](/guides/lazy-loading) to improve performance. Bundling is one of the most important challenges in web development, and solving it well can remove a lot of pain from the process. + +The good news is that, while there is some overlap, task runners and bundlers can play well together if approached in the right way. This guide provides a high-level overview of how webpack can be integrated into some of the more popular task runners. + + +## NPM Scripts + +Often webpack users use npm [`scripts`](https://docs.npmjs.com/misc/scripts) as their task runner. This is a good starting point. Cross-platform support can become a problem, but there are several workarounds for that. Many, if not most users, get by with simple npm `scripts` and various levels of webpack configuration and tooling. + +So while webpack's core focus is bundling, there are a variety of extensions that can enable you to use it for jobs typical of a task runner. Integrating a separate tool adds complexity, so be sure to weigh the pros and cons before going forward. + + +## Grunt + +For those using Grunt, we recommend the [`grunt-webpack`](https://www.npmjs.com/package/grunt-webpack) package. With `grunt-webpack` you can run webpack or [webpack-dev-server](https://github.com/webpack/webpack-dev-server) as a task, get access to stats within [template tags](https://gruntjs.com/api/grunt.template), split development and production configurations and more. Start by installing `grunt-webpack` as well as `webpack` itself if you haven't already: + +``` bash +npm install --save-dev grunt-webpack webpack +``` + +Then register a configuration and load the task: + +__Gruntfile.js__ + +``` js +const webpackConfig = require('./webpack.config.js'); + +module.exports = function(grunt) { + grunt.initConfig({ + webpack: { + options: { + stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development' + }, + prod: webpackConfig, + dev: Object.assign({ watch: true }, webpackConfig) + } + }); + + grunt.loadNpmTasks('grunt-webpack'); +}; +``` + +For more information, please visit the [repository](https://github.com/webpack-contrib/grunt-webpack). + + +## Gulp + +Gulp is also a fairly straightforward integration with the help of the [`webpack-stream`](https://github.com/shama/webpack-stream) package (a.k.a. `gulp-webpack`). In this case, it is unnecessary to install `webpack` separately as it is a direct dependency of `webpack-stream`: + +``` bash +npm install --save-dev webpack-stream +``` + +Just `require('webpack-stream')` instead of `webpack` and optionally pass it an configuration: + +__gulpfile.js__ + +``` js +var gulp = require('gulp'); +var webpack = require('webpack-stream'); +gulp.task('default', function() { + return gulp.src('src/entry.js') + .pipe(webpack({ + // Any configuration options... + })) + .pipe(gulp.dest('dist/')); +}); +``` + +For more information, please visit the [repository](https://github.com/shama/webpack-stream). + + +## Mocha + +The [`mocha-webpack`](https://github.com/zinserjan/mocha-webpack) utility can be used for a clean integration with Mocha. The repository offers more details on the pros and cons but essentially `mocha-webpack` is a simple wrapper that provides almost the same CLI as Mocha itself and provides various webpack functionality like an improved watch mode and improved path resolution. Here is a small example of how you would install it and use it to run a test suite (found within `./test`): + +``` bash +npm install --save-dev webpack mocha mocha-webpack +mocha-webpack 'test/**/*.js' +``` + +For more information, please visit the [repository](https://github.com/zinserjan/mocha-webpack). + + +## Karma + +The [`karma-webpack`](https://github.com/webpack-contrib/karma-webpack) package allows you to use webpack to pre-process files in [Karma](http://karma-runner.github.io/1.0/index.html). It also makes use of [`webpack-dev-middleware`](https://github.com/webpack/webpack-dev-middleware) and allows passing configurations for both. A simple example may look something like this: + +``` bash +npm install --save-dev webpack karma karma-webpack +``` + +__karma.conf.js__ + +``` js +module.exports = function(config) { + config.set({ + files: [ + { pattern: 'test/*_test.js', watched: false }, + { pattern: 'test/**/*_test.js', watched: false } + ], + preprocessors: { + 'test/*_test.js': [ 'webpack' ], + 'test/**/*_test.js': [ 'webpack' ] + }, + webpack: { + // Any custom webpack configuration... + }, + webpackMiddleware: { + // Any custom webpack-dev-middleware configuration... + } + }); +}; +``` + +For more information, please visit the [repository](https://github.com/webpack-contrib/karma-webpack). diff --git a/src/content/loaders/_loaders_all.md b/src/content/loaders/_loaders_all.md new file mode 100644 index 000000000000..a16e6814c65b --- /dev/null +++ b/src/content/loaders/_loaders_all.md @@ -0,0 +1,75 @@ + + +# Loaders + +webpack enables use of [loaders](/concepts/loaders) to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js. + +Loaders are activated by using `loadername!` prefixes in `require()` statements, or are automatically applied via regex from your webpack configuration – see [configuration](/concepts/loaders#configuration). + + +## Files + +- [`raw-loader`](/loaders/raw-loader) Loads raw content of a file (utf-8) +- [`val-loader`](/loaders/val-loader) Executes code as module and consider exports as JS code +- [`url-loader`](/loaders/url-loader) Works like the file loader, but can return a [data URL](https://tools.ietf.org/html/rfc2397) if the file is smaller than a limit +- [`file-loader`](/loaders/file-loader) Emits the file into the output folder and returns the (relative) URL +- [`ref-loader`](https://www.npmjs.com/package/ref-loader) Create dependencies between any files manually + + +## JSON + +- [`json-loader`](/loaders/json-loader) Loads a [JSON](http://json.org/) file (included by default) +- [`json5-loader`](/loaders/json5-loader) Loads and transpiles a [JSON 5](https://json5.org/) file +- [`cson-loader`](https://github.com/awnist/cson-loader) Loads and transpiles a [CSON](https://github.com/bevry/cson#what-is-cson) file + + +## Transpiling + +- [`script-loader`](/loaders/script-loader) Executes a JavaScript file once in global context (like in script tag), requires are not parsed +- [`babel-loader`](/loaders/babel-loader) Loads ES2015+ code and transpiles to ES5 using [Babel](https://babeljs.io/) +- [`buble-loader`](https://github.com/sairion/buble-loader) Loads ES2015+ code and transpiles to ES5 using [Bublé](https://buble.surge.sh/guide/) +- [`traceur-loader`](https://github.com/jupl/traceur-loader) Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler#readme) +- [`ts-loader`](https://github.com/TypeStrong/ts-loader) or [`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader) Loads [TypeScript](https://www.typescriptlang.org/) 2.0+ like JavaScript +- [`coffee-loader`](/loaders/coffee-loader) Loads [CoffeeScript](http://coffeescript.org/) like JavaScript +- [`fengari-loader`](https://github.com/fengari-lua/fengari-loader/) Loads Lua code using [fengari](https://fengari.io/) + + +## Templating + +- [`html-loader`](/loaders/html-loader) Exports HTML as string, require references to static resources +- [`pug-loader`](https://github.com/pugjs/pug-loader) Loads Pug and Jade templates and returns a function +- [`markdown-loader`](https://github.com/peerigon/markdown-loader) Compiles Markdown to HTML +- [`react-markdown-loader`](https://github.com/javiercf/react-markdown-loader) Compiles Markdown to a React Component using the markdown-parse parser +- [`posthtml-loader`](https://github.com/posthtml/posthtml-loader) Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) +- [`handlebars-loader`](https://github.com/pcardune/handlebars-loader) Compiles Handlebars to HTML +- [`markup-inline-loader`](https://github.com/asnowwolf/markup-inline-loader) Inline SVG/MathML files to HTML. It’s useful when applying icon font or applying CSS animation to SVG. +- [`twig-loader`](https://github.com/zimmo-be/twig-loader) Compiles Twig templates and returns a function + +## Styling + +- [`style-loader`](/loaders/style-loader) Add exports of a module as style to DOM +- [`css-loader`](/loaders/css-loader) Loads CSS file with resolved imports and returns CSS code +- [`less-loader`](/loaders/less-loader) Loads and compiles a LESS file +- [`sass-loader`](/loaders/sass-loader) Loads and compiles a SASS/SCSS file +- [`postcss-loader`](/loaders/postcss-loader) Loads and transforms a CSS/SSS file using [PostCSS](http://postcss.org) +- [`stylus-loader`](https://github.com/shama/stylus-loader) Loads and compiles a Stylus file + + +## Linting && Testing + +- [`mocha-loader`](/loaders/mocha-loader) Tests with [mocha](https://mochajs.org/) (Browser/NodeJS) +- [`eslint-loader`](https://github.com/webpack-contrib/eslint-loader) PreLoader for linting code using [ESLint](https://eslint.org/) +- [`jshint-loader`](/loaders/jshint-loader) PreLoader for linting code using [JSHint](http://jshint.com/about/) +- [`jscs-loader`](https://github.com/unindented/jscs-loader) PreLoader for code style checking using [JSCS](http://jscs.info/) +- [`coverjs-loader`](/loaders/coverjs-loader) PreLoader to determine the testing coverage using [CoverJS](https://github.com/arian/CoverJS) + + +## Frameworks + +- [`vue-loader`](https://github.com/vuejs/vue-loader) Loads and compiles [Vue Components](https://vuejs.org/v2/guide/components.html) +- [`polymer-loader`](https://github.com/webpack-contrib/polymer-webpack-loader) Process HTML & CSS with preprocessor of choice and `require()` Web Components like first-class modules +- [`angular2-template-loader`](https://github.com/TheLarkInn/angular2-template-loader) Loads and compiles [Angular](https://angular.io/) Components + + + +For more third-party loaders, see the list from [awesome-webpack](https://github.com/webpack-contrib/awesome-webpack#loaders). diff --git a/src/content/migrate/_migrate_all.md b/src/content/migrate/_migrate_all.md new file mode 100644 index 000000000000..c0c02cb9ff2b --- /dev/null +++ b/src/content/migrate/_migrate_all.md @@ -0,0 +1,786 @@ + + +# Migrate + +This section contains information about migrating from older versions of webpack to newer ones. + +# To v4 from v3 + +This guide only shows major changes that affect end users. For more details please see [the changelog](https://github.com/webpack/webpack/releases). + + +## Node.js v4 + +If you are still using Node.js v4 or lower, you need to upgrade your Node.js installation to Node.js v6 or higher. + + +## CLI + +The CLI has moved to a separate package: webpack-cli. You need to install it before using webpack, see [basic setup](/guides/getting-started/#basic-setup). + + +## Update plugins + +Many 3rd-party plugins need to be upgraded to their latest version to be compatible. + + +## mode + +Add the new [`mode`](/concepts/mode/) option to your config. Set it to production or development in your configuration depending on config type. + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + mode: 'production', +} +``` + +Alternatively you can pass it via CLI: `--mode production`/`--mode development` + +## Deprecated/Removed plugins + +These plugins can be removed from configuration as they are default in production mode: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NoEmitOnErrorsPlugin(), +- new ModuleConcatenationPlugin(), +- new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }) +- new UglifyJsPlugin() + ], +} +``` + +These plugins are default in development mode + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NamedModulesPlugin() + ], +} +``` + +These plugins were deprecated and are now removed: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + plugins: [ +- new NoErrorsPlugin(), +- new NewWatchingPlugin() + ], +} +``` + + +## CommonsChunkPlugin + +The `CommonsChunkPlugin` was removed. Instead the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) options can be used. + +See documentation of the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) for more details. The default configuration may already suit your needs. + +T> When generating the HTML from the stats you can use `optimization.splitChunks.chunks: "all"` which is the optimal configuration in most cases. + +## import() and CommonJS + +When using `import()` to load non-ESM the result has changed in webpack 4. Now you need to access the `default` property to get the value of `module.exports`. + +__non-esm.js__ + +``` javascript +module.exports = { + sayHello: () => { + console.log('hello world'); + } +}; +``` + +__example.js__ + +``` javascript +function sayHello() { + import('./non-esm.js').then(module => { + module.default.sayHello(); + }); +} +``` + +## json and loaders + +When using a custom loader to transform `.json` files you now need to change the module `type`: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + rules: [ + { + test: /config\.json$/, + loader: 'special-loader', ++ type: 'javascript/auto', + options: {...} + } + ] +}; +``` + +When still using the `json-loader`, it can be removed: + +__webpack.config.js__ + +``` diff +module.exports = { + // ... + rules: [ + { +- test: /\.json$/, +- loader: 'json-loader' + } + ] +}; +``` + +## module.loaders + +`module.loaders` were deprecated since webpack 2 and are now removed in favor of [`module.rules`](/configuration/module/#rule). + + +# To v2 or v3 from v1 + +The following sections describe the major changes from webpack 1 to 2. + +T> Note that there were far fewer changes between 2 and 3, so that migration shouldn't be too bad. If you are running into issues, please see [the changelog](https://github.com/webpack/webpack/releases) for details. + + +## `resolve.root`, `resolve.fallback`, `resolve.modulesDirectories` + +These options were replaced by a single option `resolve.modules`. See [resolving](/configuration/resolve) for more usage. + +``` diff + resolve: { +- root: path.join(__dirname, "src") ++ modules: [ ++ path.join(__dirname, "src"), ++ "node_modules" ++ ] + } +``` + + +## `resolve.extensions` + +This option no longer requires passing an empty string. This behavior was moved to `resolve.enforceExtension`. See [resolving](/configuration/resolve) for more usage. + + +## `resolve.*` + +Several APIs were changed here. Not listed in detail as it's not commonly used. See [resolving](/configuration/resolve) for details. + + +## `module.loaders` is now `module.rules` + +The old loader configuration was superseded by a more powerful rules system, which allows configuration of loaders and more. +For compatibility reasons, the old `module.loaders` syntax is still valid and the old names are parsed. +The new naming conventions are easier to understand and are a good reason to upgrade the configuration to using `module.rules`. + +``` diff + module: { +- loaders: [ ++ rules: [ + { + test: /\.css$/, +- loaders: [ +- "style-loader", +- "css-loader?modules=true" ++ use: [ ++ { ++ loader: "style-loader" ++ }, ++ { ++ loader: "css-loader", ++ options: { ++ modules: true ++ } ++ } + ] + }, + { + test: /\.jsx$/, + loader: "babel-loader", // Do not use "use" here + options: { + // ... + } + } + ] + } +``` + + +## Chaining loaders + +Like in webpack 1, loaders can be chained to pass results from loader to loader. Using the [rule.use](/configuration/module#rule-use) + configuration option, `use` can be set to an array of loaders. +In webpack 1, loaders were commonly chained with `!`. This style is only supported using the legacy option `module.loaders`. + +``` diff + module: { +- loaders: [{ ++ rules: [{ + test: /\.less$/, +- loader: "style-loader!css-loader!less-loader" ++ use: [ ++ "style-loader", ++ "css-loader", ++ "less-loader" ++ ] + }] + } +``` + + +## Automatic `-loader` module name extension removed + +It is not possible anymore to omit the `-loader` extension when referencing loaders: + +``` diff + module: { + rules: [ + { + use: [ +- "style", ++ "style-loader", +- "css", ++ "css-loader", +- "less", ++ "less-loader", + ] + } + ] + } +``` + +You can still opt-in to the old behavior with the `resolveLoader.moduleExtensions` configuration option, but this is not recommended. + +``` diff ++ resolveLoader: { ++ moduleExtensions: ["-loader"] ++ } +``` + +See [#2986](https://github.com/webpack/webpack/issues/2986) for the reason behind this change. + + +## `json-loader` is not required anymore + +When no loader has been configured for a JSON file, webpack will automatically try to load the JSON +file with the [`json-loader`](https://github.com/webpack-contrib/json-loader). + +``` diff + module: { + rules: [ +- { +- test: /\.json/, +- loader: "json-loader" +- } + ] + } +``` + +[We decided to do this](https://github.com/webpack/webpack/issues/3363) in order to iron out environment differences + between webpack, node.js and browserify. + + +## Loaders in configuration resolve relative to context + +In __webpack 1__, configured loaders resolve relative to the matched file. However, in __webpack 2__, configured loaders resolve relative to the `context` option. + +This solves some problems with duplicate modules caused by loaders when using `npm link` or referencing modules outside of the `context`. + +You may remove some hacks to work around this: + +``` diff + module: { + rules: [ + { + // ... +- loader: require.resolve("my-loader") ++ loader: "my-loader" + } + ] + }, + resolveLoader: { +- root: path.resolve(__dirname, "node_modules") + } +``` + + +## `module.preLoaders` and `module.postLoaders` were removed: + +``` diff + module: { +- preLoaders: [ ++ rules: [ + { + test: /\.js$/, ++ enforce: "pre", + loader: "eslint-loader" + } + ] + } +``` + + +## `UglifyJsPlugin` sourceMap + +The `sourceMap` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. This means that if you are using source maps for minimized code or want correct line numbers for uglifyjs warnings, you need to set `sourceMap: true` for `UglifyJsPlugin`. + +``` diff + devtool: "source-map", + plugins: [ + new UglifyJsPlugin({ ++ sourceMap: true + }) + ] +``` + + +## `UglifyJsPlugin` warnings + +The `compress.warnings` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. +This means that if you want to see uglifyjs warnings, you need to set `compress.warnings` to `true`. + +``` diff + devtool: "source-map", + plugins: [ + new UglifyJsPlugin({ ++ compress: { ++ warnings: true ++ } + }) + ] +``` + + +## `UglifyJsPlugin` minimize loaders + +`UglifyJsPlugin` no longer switches loaders into minimize mode. The `minimize: true` setting needs to be passed via loader options in the long-term. See loader documentation for relevant options. + +The minimize mode for loaders will be removed in webpack 3 or later. + +To keep compatibility with old loaders, loaders can be switched to minimize mode via plugin: + +``` diff + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ minimize: true ++ }) + ] +``` + + +## `DedupePlugin` has been removed + +`webpack.optimize.DedupePlugin` isn't needed anymore. Remove it from your configuration. + + +## `BannerPlugin` - breaking change + +`BannerPlugin` no longer accepts two parameters, but a single options object. + +``` diff + plugins: [ +- new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true}); ++ new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true}); + ] +``` + + +## `OccurrenceOrderPlugin` is now on by default + +The `OccurrenceOrderPlugin` is now enabled by default and has been renamed (`OccurenceOrderPlugin` in webpack 1). +Thus make sure to remove the plugin from your configuration: + +``` diff + plugins: [ + // webpack 1 +- new webpack.optimize.OccurenceOrderPlugin() + // webpack 2 +- new webpack.optimize.OccurrenceOrderPlugin() + ] +``` + + +## `ExtractTextWebpackPlugin` - breaking change + +[ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) requires version 2 to work with webpack 2. + +`npm install --save-dev extract-text-webpack-plugin` + +The configuration changes for this plugin are mainly syntactical. + +### `ExtractTextPlugin.extract` + +```diff +module: { + rules: [ + { + test: /.css$/, +- loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" }) ++ use: ExtractTextPlugin.extract({ ++ fallback: "style-loader", ++ use: "css-loader", ++ publicPath: "/dist" ++ }) + } + ] +} +``` + + +### `new ExtractTextPlugin({options})` + +```diff +plugins: [ +- new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false }) ++ new ExtractTextPlugin({ ++ filename: "bundle.css", ++ disable: false, ++ allChunks: true ++ }) +] +``` + + +## Full dynamic requires now fail by default + +A dependency with only an expression (i. e. `require(expr)`) will now create an empty context instead of the context of the complete directory. + +Code like this should be refactored as it won't work with ES2015 modules. If this is not possible you can use the `ContextReplacementPlugin` to hint the compiler towards the correct resolving. + +?> Link to an article about dynamic dependencies. + +### Using custom arguments in CLI and configuration + +If you abused the CLI to pass custom arguments to the configuration like so: + +`webpack --custom-stuff` + +```js +// webpack.config.js +var customStuff = process.argv.indexOf('--custom-stuff') >= 0; +/* ... */ +module.exports = config; +``` + +You may notice that this is no longer allowed. The CLI is more strict now. + +Instead there is an interface for passing arguments to the configuration. This should be used instead. Future tools may rely on this. + +`webpack --env.customStuff` + +```js +module.exports = function(env) { + var customStuff = env.customStuff; + /* ... */ + return config; +}; +``` + +See [CLI](/api/cli). + + +## `require.ensure` and AMD `require` are asynchronous + +These functions are now always asynchronous instead of calling their callback synchronously if the chunk is already loaded. + +__`require.ensure` now depends upon native `Promise`s. If using `require.ensure` in an environment that lacks them then you will need a polyfill.__ + + +## Loader configuration is through `options` + +You can _no longer_ configure a loader with a custom property in the `webpack.config.js`. It must be done through the `options`. The following configuration with the `ts` property is no longer valid with webpack 2: + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader' + }] + }, + // does not work with webpack 2 + ts: { transpileOnly: false } +}; +``` + + +### What are `options`? + +Good question. Well, strictly speaking it's 2 possible things; both ways to configure a webpack loader. Classically `options` was called `query` and was a string which could be appended to the name of the loader. Much like a query string but actually with [greater powers](https://github.com/webpack/loader-utils#parsequery): + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader?' + JSON.stringify({ transpileOnly: false }) + }] + } +}; +``` + +But it can also be a separately specified object that's supplied alongside a loader: + +```js +module.exports = { + //... + module: { + rules: [{ + test: /\.tsx?$/, + loader: 'ts-loader', + options: { transpileOnly: false } + }] + } +}; +``` + + +## `LoaderOptionsPlugin` context + +Some loaders need context information and read them from the configuration. This needs to be passed via loader options in the long-term. See loader documentation for relevant options. + +To keep compatibility with old loaders, this information can be passed via plugin: + +``` diff + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ options: { ++ context: __dirname ++ } ++ }) + ] +``` + + +## `debug` + +The `debug` option switched loaders to debug mode in webpack 1. This needs to be passed via loader options in long-term. See loader documentation for relevant options. + +The debug mode for loaders will be removed in webpack 3 or later. + +To keep compatibility with old loaders, loaders can be switched to debug mode via a plugin: + +``` diff +- debug: true, + plugins: [ ++ new webpack.LoaderOptionsPlugin({ ++ debug: true ++ }) + ] +``` + + +## Code Splitting with ES2015 + +In webpack 1, you could use [`require.ensure()`](/api/module-methods#require-ensure) as a method to lazily-load chunks for your application: + +```javascript +require.ensure([], function(require) { + var foo = require('./module'); +}); +``` + +The ES2015 Loader spec defines [`import()`](/api/module-methods#import-) as method to load ES2015 Modules dynamically on runtime. webpack treats `import()` as a split-point and puts the requested module in a separate chunk. `import()` takes the module name as argument and returns a Promise. + +```js +function onClick() { + import('./module').then(module => { + return module.default; + }).catch(err => { + console.log('Chunk loading failed'); + }); +} +``` + +Good news: Failure to load a chunk can now be handled because they are `Promise` based. + + +## Dynamic expressions + +It's possible to pass a partial expression to `import()`. This is handled similar to expressions in CommonJS (webpack creates a [context](/plugins/context-replacement-plugin/) with all possible files). + +`import()` creates a separate chunk for each possible module. + +```js +function route(path, query) { + return import(`./routes/${path}/route`) + .then(route => new route.Route(query)); +} +// This creates a separate chunk for each possible route +``` + + +## Mixing ES2015 with AMD and CommonJS + +As for AMD and CommonJS you can freely mix all three module types (even within the same file). webpack behaves similar to babel and node-eps in this case: + +```javascript +// CommonJS consuming ES2015 Module +var book = require('./book'); + +book.currentPage; +book.readPage(); +book.default === 'This is a book'; +``` + +```javascript +// ES2015 Module consuming CommonJS +import fs from 'fs'; // module.exports map to default +import { readFileSync } from 'fs'; // named exports are read from returned object+ + +typeof fs.readFileSync === 'function'; +typeof readFileSync === 'function'; +``` + +It is important to note that you will want to tell Babel to not parse these module symbols so webpack can use them. You can do this by setting the following in your `.babelrc` or `babel-loader` options. + +__.babelrc__ + +```json +{ + "presets": [ + ["es2015", { "modules": false }] + ] +} +``` + + +## Hints + +No need to change something, but opportunities + +### Template strings + +webpack now supports template strings in expressions. This means you can start using them in webpack constructs: + +``` diff +- require("./templates/" + name); ++ require(`./templates/${name}`); +``` + + +### Configuration Promise + +webpack now supports returning a `Promise` from the configuration file. This allows async processing in your configuration file. + +__webpack.config.js__ + +```js +module.exports = function() { + return fetchLangs().then(lang => ({ + entry: '...', + // ... + plugins: [ + new DefinePlugin({ LANGUAGE: lang }) + ] + })); +}; +``` + + +### Advanced loader matching + +webpack now supports more things to match on for loaders. + +```js +module.exports = { + //... + module: { + rules: [ + { + resource: /filename/, // matches "/path/filename.js" + resourceQuery: /^\?querystring$/, // matches "?querystring" + issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js" + } + ] + } +}; +``` + + +### More CLI options + +There are some new CLI options for you to use: + +`--define process.env.NODE_ENV="production"` See [`DefinePlugin`](/plugins/define-plugin/). + +`--display-depth` displays the distance to the entry point for each module. + +`--display-used-exports` display info about which exports are used in a module. + +`--display-max-modules` sets the number for modules displayed in the output (defaults to 15). + +`-p` also defines `process.env.NODE_ENV` to `"production"` now. + + +## Loader changes + +Changes only relevant for loader authors. + + +### Cacheable + +Loaders are now cacheable by default. Loaders must opt-out if they are not cacheable. + +``` diff + // Cacheable loader + module.exports = function(source) { +- this.cacheable(); + return source; + } +``` + +``` diff + // Not cacheable loader + module.exports = function(source) { ++ this.cacheable(false); + return source; + } +``` + + +### Complex options + +__webpack 1__ only supports `JSON.stringify`-able options for loaders. + +__webpack 2__ now supports any JS object as loader options. + +Before webpack [2.2.1](https://github.com/webpack/webpack/releases/tag/v2.2.1) (i.e. from 2.0.0 through 2.2.0), using complex options required using `ident` for the `options` object to allow its reference from other loaders. __This was removed in 2.2.1__ and thus current migrations do not require any use of the `ident` key. + +```diff +{ + test: /\.ext/ + use: { + loader: '...', + options: { +- ident: 'id', + fn: () => require('./foo.js') + } + } +} +``` diff --git a/src/content/plugins/_plugins_all.md b/src/content/plugins/_plugins_all.md new file mode 100644 index 000000000000..65d63475ab80 --- /dev/null +++ b/src/content/plugins/_plugins_all.md @@ -0,0 +1,11 @@ + + +# MinChunkSizePlugin + +Keep chunk size above the specified limit by merging chunks that are smaller than the `minChunkSize`. + +``` js +new webpack.optimize.MinChunkSizePlugin({ + minChunkSize: 10000 // Minimum number of characters +}); +``` From 6603ced6aaac7d3167da68637493c14da76ce735 Mon Sep 17 00:00:00 2001 From: Axel D <SetTrend@users.noreply.github.com> Date: Sun, 13 Jan 2019 22:55:36 +0100 Subject: [PATCH 12/13] _all.md files removed, .gitigore amened to exclude _all.md files from being checked in. --- src/content/_all.md | 262 - src/content/api/_api_all.md | 3189 ---------- src/content/concepts/_concepts_all.md | 1086 ---- .../configuration/_configuration_all.md | 5315 ----------------- src/content/contribute/_contribute_all.md | 979 --- src/content/guides/_guides_all.md | 4880 --------------- src/content/loaders/_loaders_all.md | 75 - src/content/migrate/_migrate_all.md | 786 --- src/content/plugins/_plugins_all.md | 11 - 9 files changed, 16583 deletions(-) delete mode 100644 src/content/_all.md delete mode 100644 src/content/api/_api_all.md delete mode 100644 src/content/concepts/_concepts_all.md delete mode 100644 src/content/configuration/_configuration_all.md delete mode 100644 src/content/contribute/_contribute_all.md delete mode 100644 src/content/guides/_guides_all.md delete mode 100644 src/content/loaders/_loaders_all.md delete mode 100644 src/content/migrate/_migrate_all.md delete mode 100644 src/content/plugins/_plugins_all.md diff --git a/src/content/_all.md b/src/content/_all.md deleted file mode 100644 index fb91d2979380..000000000000 --- a/src/content/_all.md +++ /dev/null @@ -1,262 +0,0 @@ - - -# Comparison - -webpack is not the only module bundler out there. If you are choosing between using webpack or any of the bundlers below, here is a feature-by-feature comparison on how webpack fares against the current competition. - -| Feature | webpack/webpack | jrburke/requirejs | substack/node-browserify | jspm/jspm-cli | rollup/rollup | brunch/brunch | -|---------|-----------------|-------------------|--------------------------|---------------|---------------|---------------| -| Additional chunks are loaded on demand | __yes__ | __yes__ | no | [System.import](https://github.com/systemjs/systemjs/blob/master/docs/system-api.md#systemimportmodulename--normalizedparentname---promisemodule) | no | no | -| AMD `define` | __yes__ | __yes__ | [deamdify](https://github.com/jaredhanson/deamdify) | yes | [rollup-plugin-amd](https://github.com/piuccio/rollup-plugin-amd) | yes | -| AMD `require` | __yes__ | __yes__ | no | yes | no | yes | -| AMD `require` loads on demand | __yes__ | with manual configuration | no | yes | no | no | -| CommonJS `exports` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | -| CommonJS `require` | __yes__ | only wrapping in `define` | __yes__ | yes | [commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs) | yes | -| CommonJS `require.resolve` | __yes__ | no | no | no | no | | -| Concat in require `require("./fi" + "le")` | __yes__ | no♦ | no | no | no | | -| Debugging support | __SourceUrl, SourceMaps__ | not required | SourceMaps | __SourceUrl, SourceMaps__ | __SourceUrl, SourceMaps__ | SourceMaps | -| Dependencies | 19MB / 127 packages | 11MB / 118 packages | __1.2MB / 1 package__ | 26MB / 131 packages | ?MB / 3 packages | | -| ES2015 `import`/`export` | __yes__ (webpack 2) | no | no | __yes__ | __yes__ | yes, via [es6 module transpiler](https://github.com/gcollazo/es6-module-transpiler-brunch) -| Expressions in require (guided) `require("./templates/" + template)` | __yes (all files matching included)__ | no♦ | no | no | no | no | -| Expressions in require (free) `require(moduleName)` | with manual configuration | no♦ | no | no | no | | -| Generate a single bundle | __yes__ | yes♦ | yes | yes | yes | yes | -| Indirect require `var r = require; r("./file")` | __yes__ | no♦ | no | no | no | | -| Load each file separate | no | yes | no | yes | no | no | -| Mangle path names | __yes__ | no | partial | yes | not required (path names are not included in the bundle) | no | -| Minimizing | terser | uglify, closure compiler | [uglifyify](https://github.com/hughsk/uglifyify) | yes | [uglify-plugin](https://github.com/TrySound/rollup-plugin-uglify) | [UglifyJS-brunch](https://github.com/brunch/uglify-js-brunch) -| Multi pages build with common bundle | with manual configuration | __yes__ | with manual configuration | with bundle arithmetic | no | no| -| Multiple bundles | __yes__ | with manual configuration | with manual configuration | yes | no | yes | -| Node.js built-in libs `require("path")` | __yes__ | no | __yes__ | __yes__ | [node-resolve-plugin](https://github.com/rollup/rollup-plugin-node-resolve) | | -| Other Node.js stuff | process, __dir/filename, global | - | process, __dir/filename, global | process, __dir/filename, global for cjs | global ([commonjs-plugin](https://github.com/rollup/rollup-plugin-commonjs)) | | -| Plugins | __yes__ | yes | __yes__ | yes | yes | yes | -| Preprocessing | __loaders, [transforms](https://github.com/webpack-contrib/transform-loader)__ | loaders | transforms | plugin translate | plugin transforms | compilers, optimizers | -| Replacement for browser | `web_modules`, `.web.js`, package.json field, alias config option | alias option | package.json field, alias option | package.json, alias option | no | | -| Requirable files | file system | __web__ | file system | through plugins | file system or through plugins | file system | -| Runtime overhead | __243B + 20B per module + 4B per dependency__ | 14.7kB + 0B per module + (3B + X) per dependency | 415B + 25B per module + (6B + 2X) per dependency | 5.5kB for self-executing bundles, 38kB for full loader and polyfill, 0 plain modules, 293B CJS, 139B ES2015 System.register before gzip | __none for ES2015 modules__ (other formats may have) | | -| Watch mode | yes | not required | [watchify](https://github.com/browserify/watchify) | not needed in dev | [rollup-watch](https://github.com/rollup/rollup-watch) | yes | - -♦ in production mode (opposite in development mode) - -X is the length of the path string - - -## Bundling vs. Loading - -It's important to note some key differences between _loading_ and _bundling_ modules. A tool like [SystemJS](https://github.com/systemjs/systemjs), which can be found under the hood of [JSPM](https://github.com/jspm/jspm-cli), is used to load and transpile modules at runtime in the browser. This differs significantly from webpack, where modules are transpiled (through "loaders") and bundled before hitting the browser. - -Each method has its advantages and disadvantages. Loading and transpiling modules at runtime can add a lot of overhead for larger sites and applications comprised of many modules. For this reason, SystemJS makes more sense for smaller projects where fewer modules are required. However, this may change a bit as [HTTP/2](https://http2.github.io/) will improve the speed at which files can be transferred from server to client. Note that HTTP/2 doesn't change anything about _transpiling_ modules, which will always take longer when done client-side. - - -# Branding Guidelines - -Here you can find __webpack__ project brand guidelines, assets, and license. See our official [media repository](https://github.com/webpack/media) for more information and to find the [license](https://github.com/webpack/media/blob/master/LICENSE) that governs this work. Click any of the images to download them. - - -## The Name - -webpack should __always__ be written in lower-case letters, even at the beginning of a sentence. - - -## Logo - -The webpack logo should be placed on a white background with enough space around it like this: - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-white-bg.png" alt="webpack logo default with proper spacing on light background" /> - -[svg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-white-bg.jpg) - -Just double the size of the inner dark blue cube to get an idea how much space the logo should have. - -For dark backgrounds, you can use the negative version of the logo: - -<div style="display: block; background: #111;"> - <img src="https://raw.githubusercontent.com/webpack/media/master/logo/logo-on-dark-bg.png" alt="webpack logo default with proper spacing on light background" /> -</div> - -[svg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.svg) | [png](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.png) | [jpg](https://github.com/webpack/media/blob/master/logo/logo-on-dark-bg.jpg) - -T> Please use the __icon + text__ whenever possible. - - -## Icon only - -__The icon is designed to be used in layout-constrained areas. As previously stated, please prefer icon + text.__ - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon.png" width="250" alt="icon example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon.jpg) - -Square-sized icon for bigger areas (like avatars or profile pictures): - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-big.png" width="250" alt="icon square big example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon-square-big.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-big.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-big.jpg) - -Square-sized icon for smaller areas (like favicons): - -<img src="https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-small.png" width="50" alt="icon square small example"> - -[svg](https://github.com/webpack/media/blob/master/logo/icon-square-small.svg) | [png](https://github.com/webpack/media/blob/master/logo/icon-square-small.png) | [jpg](https://github.com/webpack/media/blob/master/logo/icon-square-small.jpg) - -T> For those of you following our guidelines and have gotten this far, we've made a special smaller size image used especially for custom emoji (like in a slack or gitter channel ;)) - -<img src="/assets/icon-square-small-slack.png" width="50" alt="icon square small example"> - - -## Font - -We use the beautiful [Geomanist Medium](http://atipofoundry.com/fonts/geomanist) font from the extremely talented folks at the [Atipo Foundry](http://atipofoundry.com/) who provide the entire font family at a 'pay what you want' model. - - -## Color Palette - -The following colors are used throughout the site in various combinations and on our fancy clothing line launched with the help of [Open Collective](https://opencollective.com/) and [Threadless](https://medium.com/u/840563ee2a56) over at the [official webpack store](https://webpack.threadless.com/collections/the-final-release-collection/)! - -| Color Name | HEX Code | RGB Code | Sample -|---------------|---------------|-----------------------|------------------------------- -| Malibu: | HEX `#8dd6f9` | `rgb: 141, 214, 249` | <div style="background-color: #8dd6f9;"> </div> -| Denim: | HEX `#1d78c1` | `rgb: 29, 120, 193` | <div style="background-color: #1d78c1;"> </div> -| Fiord: | HEX `#465E69` | `rgb: 70, 94, 105` | <div style="background-color: #465E69;"> </div> -| Outer Space: | HEX `#2B3A42` | `rgb: 43, 58, 66` | <div style="background-color: #2B3A42;"> </div> -| White: | HEX `#ffffff` | `rgb: 255, 255, 255` | <div style="background-color: #ffffff;"> </div> -| Concrete: | HEX `#f2f2f2` | `rgb: 242, 242, 242` | <div style="background-color: #f2f2f2;"> </div> -| Alto: | HEX `#dedede` | `rgb: 222, 222, 222` | <div style="background-color: #dedede;"> </div> -| Dusty Gray: | HEX `#999999` | `rgb: 153, 153, 153` | <div style="background-color: #999999;"> </div> -| Dove Gray: | HEX `#666666` | `rgb: 102, 102, 102` | <div style="background-color: #666666;"> </div> -| Emperor: | HEX `#535353` | `rgb: 83, 83, 83` | <div style="background-color: #535353;"> </div> -| Mine Shaft: | HEX `#333333` | `rgb: 51, 51, 51` | <div style="background-color: #333333;"> </div> - -In addition, you can grab the following file types directly from these links: - -[psd](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.psd) | [png](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.png) - | [ai](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.ai) | [svg](https://raw.githubusercontent.com/webpack/media/master/design/webpack-palette.svg) - - -## License - -The logo and the brand name are __not MIT licensed__. Please check [our LICENSE](https://github.com/webpack/media/blob/master/LICENSE) for usage guidelines. - - -# Glossary - -This index lists common terms used throughout the webpack ecosystem. - - -## A - -- [__Asset__](/guides/asset-management/): This a general term for the images, fonts, media, and any other kind of files that are typically used in websites and other applications. These typically end up as individual files within the [output](/glossary#o) but can also be inlined via things like the [style-loader](/loaders/style-loader) or [url-loader](/loaders/url-loader). - - -## B - -- [__Bundle__](/guides/getting-started/#creating-a-bundle): Produced from a number of distinct modules, bundles contain the final versions of source files that have already undergone the loading and compilation process. -- [__Bundle Splitting__](/guides/code-splitting): This process offers one way of optimizing a build, allowing webpack to generate multiple bundles for a single application. As a result, each bundle can be isolated from changes effecting others, reducing the amount of code that needs to be republished and therefore re-downloaded by the client and taking advantage of browser caching. - - -## C - -- __Chunk__: This webpack-specific term is used internally to manage the bundling process. Bundles are composed out of chunks, of which there are several types (e.g. entry and child). Typically, _chunks_ directly correspond with the output _bundles_ however, there are some configurations that don't yield a one-to-one relationship. -- [__Code Splitting__](/guides/code-splitting/): Refers to dividing your code into various bundles/chunks which you can then load on demand instead of loading a single bundle containing everything. -- [__Configuration__](/concepts/configuration/): webpack config file is a plain old JavaScript file that exports an object. This object is then processed by webpack based upon its defined properties. - - -## D - -- [__Dependency Graph__](/concepts/dependency-graph): Any time one file depends on another, webpack treats this as a _dependency_. Starting from an entry point(s), webpack recursively builds a dependency graph that includes every module/asset your application needs. - - -## E - -- [__Entry Point__](/concepts/entry-points): The entry point tells webpack where to start and follows the graph of dependencies to know what to bundle. You can think of your application's entry point(s) as the __contextual root(s)__ of what you want bundled. - - -## F - -## G - -## H - -- [__Hot Module Replacement (HMR)__](/concepts/hot-module-replacement): A process that exchanges, adds, or removes `modules` while an application is running without a full page reload. - - -## I - -## J - -## K - -## L - -- [__Loaders__](/concepts/loaders): Transformations that are applied on the source code of a module. They allow you to pre-process files as you `require()` or "load" them. Similar to a 'task-runner'. - - -## M - -- [__Module__](/concepts/modules): Discrete chunks of functionality that provide a smaller surface area than a full program. Well-written modules provide solid abstractions and encapsulation boundaries which make up a coherent design and clear purpose. -- [__Module Resolution__](/concepts/module-resolution/): A module can be required as a dependency from another module and a resolver is a library which helps in locating a module by its absolute path.. Modules are searched for inside all directories specified in `resolve.modules`. - - -## N - -## O - -- [__Output__](/concepts/output): Option(s) specifying where to output the compiled files to disk. - > _Note, that while there can be multiple entry points, only one output configuration is specified._ - - -## P - -- [__Plugin__](/concepts/plugins): A JavaScript object that has an `apply` property. This `apply` property is called by the webpack compiler, giving access to the entire compilation lifecycle. These packages will typically extend compilation functionality in one way or another. - - -## Q - -## R - -- [__Request__](/guides/dependency-management/): Refers to the expression in the require/import statement, e.g. _require("./template/" + name + ".ejs")_, the request is _"./template/" + name + ".ejs"_. - -## S - -## T - -- [__Target__](/configuration/target/): User configured deployment target(s) [listed here](/configuration/target/) to compile for a specific environment like the browser, NodeJS, or Electron. -- [__Tree Shaking__](/guides/tree-shaking/): Unused/Excess code elimination, or more precisely, live code importing. Compilers like webpack will accomplish this by analyzing the various kinds `import` statements and usage of the imported code to determine what parts of dependencies are actually being utilized, dropping parts of the "tree" that are not. - - -## U - -## V - -- [__Vendor Entry Point__](/concepts/entry-points/#separate-app-and-vendor-entries): Create dependency graphs starting at both `app.js` and `vendors.js`. These graphs are completely separate and independent of each other to allow leverage of `CommonsChunkPlugin` and extract any vendor references from your app bundle into your vendor bundle. Helps achieve a common pattern in webpack known as [long-term vendor-caching](/guides/caching/). - - -## W - -- [__webpack__](/): A highly configurable [module](/concepts/modules) bundler for modern JavaScript applications - - -## X - -## Y - -## Z - - -# License - -## webpack - -webpack is [MIT licensed](https://github.com/webpack/webpack/blob/master/LICENSE). - -## webpack logo and icon - -The webpack logo and icon are under a different license which can be -found [here](https://github.com/webpack/media). - -## webpack documentation - -The content on [https://webpack.js.org/](https://webpack.js.org/) is available under [Creative Commons BY 4.0](https://creativecommons.org/licenses/by/4.0/) license meaning attribution is required should you use the content elsewhere. - -## webpack code samples - -The code samples use [CC0 1.0 Universal (CC0 1.0) (Public Domain)](https://creativecommons.org/publicdomain/zero/1.0/) and you are free to use them as you like. diff --git a/src/content/api/_api_all.md b/src/content/api/_api_all.md deleted file mode 100644 index d54e6da2b86f..000000000000 --- a/src/content/api/_api_all.md +++ /dev/null @@ -1,3189 +0,0 @@ - - -# Compiler Hooks - -The `Compiler` module is the main engine that creates a compilation instance -with all the options passed through the [CLI](/api/cli) or [Node API](/api/node). It extends the -`Tapable` class in order to register and call plugins. Most user facing plugins -are first registered on the `Compiler`. - -T> This module is exposed as `webpack.Compiler` and can be used directly. See -[this example](https://github.com/pksjce/webpack-internal-examples/tree/master/compiler-example) -for more information. - -When developing a plugin for webpack, you might want to know where each hook is called. To learn this, search for `hooks.<hook name>.call` across the webpack source - - -## Watching - -The `Compiler` supports [watching](/api/node/#watching) which monitors the file -system and recompiles as files change. When in watch mode, the compiler will -emit the additional events such as `watchRun`, `watchClose`, and `invalid`. -This is typically used in [development](/guides/development), usually under -the hood of tools like `webpack-dev-server`, so that the developer doesn't -need to re-compile manually every time. Watch mode can also be entered via the -[CLI](/api/cli/#watch-options). - - -## Hooks - -The following lifecycle hooks are exposed by the `compiler` and can be accessed -as such: - -``` js -compiler.hooks.someHook.tap(/* ... */); -``` - -Depending on the hook type, `tapAsync` and `tapPromise` may also be available. - -For the description of hook types, see [the Tapable docs](https://github.com/webpack/tapable#hook-types). - - -### `entryOption` - -`SyncBailHook` - -Executes a plugin after [the `entry` configuration](https://webpack.js.org/configuration/entry-context/#entry) from webpack options has been processed. - - -### `afterPlugins` - -`SyncHook` - -Runs a plugin after setting up initial set of plugins. - -Parameters: `compiler` - - -### `afterResolvers` - -`SyncHook` - -Executes a plugin after resolver setup is complete. - -Parameters: `compiler` - - -### `environment` - -`SyncHook` - -Runs a plugin before the environment is prepared. - - -### `afterEnvironment` - -`SyncHook` - -Executes a plugin a environment setup is complete. - - -### `beforeRun` - -`AsyncSeriesHook` - -Adds a hook right before `compiler.run()` is executed. - -Parameters: `compiler` - - -### `run` - -`AsyncSeriesHook` - -Hook into the compiler before it begins reading records. - -Parameters: `compiler` - - -### `watchRun` - -`AsyncSeriesHook` - -Executes a plugin during watch mode after a new compilation is triggered -but before the compilation is actually started. - -Parameters: `compiler` - - -### `normalModuleFactory` - -`SyncHook` - -Runs a plugin after a `NormalModuleFactory` is created. - -Parameters: `normalModuleFactory` - - -### `contextModuleFactory` - -Runs a plugin after a `ContextModuleFactory` is created. - -Parameters: `contextModuleFactory` - - -### `beforeCompile` - -`AsyncSeriesHook` - -Executes a plugin after compilation parameters are created. - -Parameters: `compilationParams` - - -### `compile` - -`SyncHook` - -Hook into the compiler before a new compilation is created. - -Parameters: `compilationParams` - - -### `thisCompilation` - -`SyncHook` - -Executed before emitting the `compilation` event (see below). - -Parameters: `compilation` - - -### `compilation` - -`SyncHook` - -Runs a plugin after a compilation has been created. - -Parameters: `compilation` - - -### `make` - -`AsyncParallelHook` - -... - -Parameters: `compilation` - - -### `afterCompile` - -`AsyncSeriesHook` - -... - -Parameters: `compilation` - - -### `shouldEmit` - -`SyncBailHook` - -Can return true/false at this point - -Parameters: `compilation` - - -### `emit` - -`AsyncSeriesHook` - -Before emitting assets to output dir - -Parameters: `compilation` - - -### `afterEmit` - -`AsyncSeriesHook` - -After emitting assets to output dir - -Parameters: `compilation` - - -### `done` - -`AsyncSeriesHook` - -Compilation has completed. - -Parameters: `stats` - - -### `failed` - -`SyncHook` - -Compilation has failed. - -Parameters: `error` - - -### `invalid` - -`SyncHook` - -Watch compilation has been invalidated. - -Parameters: `fileName`, `changeTime` - - -### `watchClose` - -`SyncHook` - -Watch mode has stopped. - - -# Introduction - -A variety of interfaces are available to customize the compilation process. -Some features overlap between interfaces, e.g. a configuration option may be -available via a CLI flag, while others exist only through a single interface. -The following high-level information should get you started. - - -## CLI - -The Command Line Interface (CLI) to configure and interact with your build. It -is especially useful in the case of early prototyping and profiling. For the -most part, the CLI is simply used to kick off the process using a configuration -file and a few flags (e.g. `--env`). - -[Learn more about the CLI!](/api/cli) - - -## Module - -When processing modules with webpack, it is important to understand the -different module syntaxes -- specifically the [methods](/api/module-methods) -and [variables](/api/module-variables) -- that are supported. - -[Learn more about modules!](/api/module-methods) - - -## Node - -While most users can get away with just using the CLI along with a -configuration file, more fine-grained control of the compilation can be -achieved via the Node interface. This includes passing multiple configurations, -programmatically running or watching, and collecting stats. - -[Learn more about the Node API!](/api/node) - - -## Loaders - -Loaders are transformations that are applied to the source code of a module. -They are written as functions that accept source code as a parameter and return -a new version of that code with transformations applied. - -[Learn more about loaders!](/api/loaders) - - -## Plugins - -The plugin interface allows users to tap directly into the compilation process. -Plugins can register handlers on lifecycle hooks that run at different points -throughout a compilation. When each hook is executed, the plugin will have full -access to the current state of the compilation. - -[Learn more about plugins!](/api/plugins) - - -# Command Line Interface - -For proper usage and easy distribution of this configuration, webpack can be configured with `webpack.config.js`. Any parameters sent to the CLI will map to a corresponding parameter in the config file. - -Read the [installation guide](/guides/installation) if you don't already have webpack and CLI installed. - - -## Usage with config file - -```sh -webpack [--config webpack.config.js] -``` - -See [configuration](/configuration) for the options in the configuration file. - - -## Usage without config file - -```sh -webpack <entry> [<entry>] -o <output> -``` - -__`<entry>`__ - -A filename or a set of named filenames which act as the entry point to build your project. You can pass multiple entries (every entry is loaded on startup). If you pass a pair in the form `<name>=<request>` you can create an additional entry point. It will be mapped to the configuration option `entry`. - -__`<output>`__ - -A path and filename for the bundled file to be saved in. It will be mapped to the configuration options `output.path` and `output.filename`. - -__Example__ - -If your project structure is as follows - - -```bash -. -├── dist -├── index.html -└── src - ├── index.js - ├── index2.js - └── others.js -``` - -```bash -webpack src/index.js -o dist/bundle.js -``` - -This will bundle your source code with entry as `index.js` and the output bundle file will have a path of `dist` and the filename will be `bundle.js` - -```bash - | Asset | Size | Chunks | Chunk Names | - |-----------|---------|-------------|-------------| - | bundle.js | 1.54 kB | 0 [emitted] | index | - [0] ./src/index.js 51 bytes {0} [built] - [1] ./src/others.js 29 bytes {0} [built] -``` - -```bash -webpack index=./src/index.js entry2=./src/index2.js dist/bundle.js -``` - -This will form the bundle with both the files as separate entry points. - -```bash - | Asset | Size | Chunks | Chunk Names | - |-----------|---------|---------------|---------------| - | bundle.js | 1.55 kB | 0,1 [emitted] | index, entry2 | - [0] ./src/index.js 51 bytes {0} [built] - [0] ./src/index2.js 54 bytes {1} [built] - [1] ./src/others.js 29 bytes {0} {1} [built] -``` - - -### Common Options - -W> Note that Command Line Interface has a higher precedence for the arguments you use it with than your configuration file. For instance, if you pass [`--mode="production"`](/concepts/mode/#usage) to webpack CLI and your configuration file uses `development`, `production` will be used. - -__List all of the options available on the cli__ - -```bash -webpack --help -webpack -h -``` - -__Build source using a config file__ - -Specifies a different [configuration](/configuration) file to pick up. Use this if you want to specify something different than `webpack.config.js`, which is the default. - -```bash -webpack --config example.config.js -``` - -__Print result of webpack as a JSON__ - -```bash -webpack --json -webpack --json > stats.json -``` - -In every other case, webpack prints out a set of stats showing bundle, chunk and timing details. Using this option the output can be a JSON object. This response is accepted by webpack's [analyse tool](https://webpack.github.io/analyse/), or chrisbateman's [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/), or th0r's [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). The analyse tool will take in the JSON and provide all the details of the build in graphical form. - -### Environment Options - -When the webpack configuration [exports a function](/configuration/configuration-types#exporting-a-function), an "environment" may be passed to it. - -```bash -webpack --env.production # sets env.production == true -webpack --env.platform=web # sets env.platform == "web" -``` - -The `--env` argument accepts various syntaxes: - -Invocation | Resulting environment ----------------------------------------- | --------------------------- -`webpack --env prod` | `"prod"` -`webpack --env.prod` | `{ prod: true }` -`webpack --env.prod=1` | `{ prod: 1 }` -`webpack --env.prod=foo` | `{ prod: "foo" }` -`webpack --env.prod --env.min` | `{ prod: true, min: true }` -`webpack --env.prod --env min` | `[{ prod: true }, "min"]` -`webpack --env.prod=foo --env.prod=bar` | `{prod: [ "foo", "bar" ]}` - -T> See the [environment variables](/guides/environment-variables) guide for more information on its usage. - -### Config Options - -Parameter | Explanation | Input type | Default -------------------------- | ------------------------------------------- | ---------- | ------------------ -`--config` | Path to the config file | string | webpack.config.js or webpackfile.js -`--config-register, -r` | Preload one or more modules before loading the webpack configuration | array | -`--config-name` | Name of the config to use | string | -`--env` | Environment passed to the config, when it is a function | | -`--mode` | Mode to use, either "development" or "production" | string | - -### Output Options - -This set of options allows you to manipulate certain [output](/configuration/output) parameters of your build. - -Parameter | Explanation | Input type | Default -------------------------- | ------------------------------------------- | ---------- | ------------------ -`--output-chunk-filename` | The output filename for additional chunks | string | filename with [id] instead of [name] or [id] prefixed -`--output-filename` | The output filename of the bundle | string | [name].js -`--output-jsonp-function` | The name of the JSONP function used for chunk loading | string | webpackJsonp -`--output-library` | Expose the exports of the entry point as library | string | -`--output-library-target` | The type for exposing the exports of the entry point as library | string | var -`--output-path` | The output path for compilation assets | string | Current directory -`--output-pathinfo` | Include a comment with the request for every dependency | boolean | false -`--output-public-path` | The public path for the assets | string | / -`--output-source-map-filename` | The output filename for the SourceMap | string | [name].map or [outputFilename].map -`--build-delimiter` | Display custom text after build output | string | Default string is null. You could provide a string such as `=== Build done ===` - - -#### Example Usage - -```bash -webpack index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' - -| Asset | Size | Chunks | Chunk Names | -|--------------------------------------|---------|-------------|---------------| -| index2740fdca26e9348bedbec.bundle.js | 2.6 kB | 0 [emitted] | index2 | -| index740fdca26e9348bedbec.bundle.js | 2.59 kB | 1 [emitted] | index | - [0] ./src/others.js 29 bytes {0} {1} [built] - [1] ./src/index.js 51 bytes {1} [built] - [2] ./src/index2.js 54 bytes {0} [built] -``` - -```bash -webpack.js index=./src/index.js index2=./src/index2.js --output-path='./dist' --output-filename='[name][hash].bundle.js' --devtool source-map --output-source-map-filename='[name]123.map' - -| Asset | Size | Chunks | Chunk Names | -|--------------------------------------|---------|-------------|---------------| -| index2740fdca26e9348bedbec.bundle.js | 2.76 kB | 0 [emitted] | index2 | -| index740fdca26e9348bedbec.bundle.js | 2.74 kB | 1 [emitted] | index | -| index2123.map | 2.95 kB | 0 [emitted] | index2 | -| index123.map | 2.95 kB | 1 [emitted] | index | - [0] ./src/others.js 29 bytes {0} {1} [built] - [1] ./src/index.js 51 bytes {1} [built] - [2] ./src/index2.js 54 bytes {0} [built] -``` - - -### Debug Options - -This set of options allows you to better debug the application containing assets compiled with webpack - -Parameter | Explanation | Input type | Default value ------------- | ------------------------------------------------ | ---------- | ------------- -`--debug` | Switch loaders to debug mode | boolean | false -`--devtool` | Define [source map type](/configuration/devtool/) for the bundled resources | string | - -`--progress` | Print compilation progress in percentage | boolean | false -`--display-error-details` | Display details about errors | boolean | false - -### Module Options - -These options allow you to bind [modules](/configuration/module/) as allowed by webpack - -Parameter | Explanation | Usage --------------------- | -------------------------------------- | ---------------- -`--module-bind` | Bind a file extension to a loader | `--module-bind js=babel-loader` -`--module-bind-post` | Bind a file extension to a post loader | -`--module-bind-pre` | Bind a file extension to a pre loader | - - -### Watch Options - -These options makes the build [watch](/configuration/watch/) for changes in files of the dependency graph and perform the build again. - -Parameter | Explanation -------------------------- | ---------------------- -`--watch`, `-w` | Watch the filesystem for changes -`--watch-aggregate-timeout` | Timeout for gathering changes while watching -`--watch-poll` | The polling interval for watching (also enable polling) -`--watch-stdin`, `--stdin` | Exit the process when stdin is closed - - -### Optimize Options - -These options allow you to manipulate optimisations for a production build using webpack - -Parameter | Explanation | Plugin Used ---------------------------- | -------------------------------------------------------|---------------------- -`--optimize-max-chunks` | Try to keep the chunk count below a limit | [LimitChunkCountPlugin](/plugins/limit-chunk-count-plugin) -`--optimize-min-chunk-size` | Try to keep the chunk size above a limit | [MinChunkSizePlugin](/plugins/min-chunk-size-plugin) -`--optimize-minimize` | Minimize javascript and switches loaders to minimizing | [TerserPlugin](/plugins/terser-webpack-plugin/) & [LoaderOptionsPlugin](/plugins/loader-options-plugin/) - - -### Resolve Options - -These allow you to configure the webpack [resolver](/configuration/resolve/) with aliases and extensions. - -Parameter | Explanation | Example ----------------------- | ------------------------------------------------------- | ------------- -`--resolve-alias` | Setup a module alias for resolving | --resolve-alias jquery-plugin=jquery.plugin -`--resolve-extensions` | Setup extensions that should be used to resolve modules | --resolve-extensions .es6 .js .ts -`--resolve-loader-alias` | Minimize javascript and switches loaders to minimizing | - - -### Stats Options - -These options allow webpack to display various [stats](/configuration/stats/) and style them differently in the console output. - -Parameter | Explanation | Type --------------------------------- | ------------------------------------------------------------------ | ------- -`--color`, `--colors` | Force colors on the console [default: enabled for TTY output only] | boolean -`--no-color`, `--no-colors` | Force no colors on the console | boolean -`--display` | Select [display preset](/configuration/stats) (verbose, detailed, normal, minimal, errors-only, none; since webpack 3.0.0) | string -`--display-cached` | Display also cached modules in the output | boolean -`--display-cached-assets` | Display also cached assets in the output | boolean -`--display-chunks` | Display chunks in the output | boolean -`--display-depth` | Display distance from entry point for each module | boolean -`--display-entrypoints` | Display entry points in the output | boolean -`--display-error-details` | Display details about errors | boolean -`--display-exclude` | Exclude modules in the output | boolean -`--display-max-modules` | Sets the maximum number of visible modules in output | number -`--display-modules` | Display even excluded modules in the output | boolean -`--display-optimization-bailout` | Scope hoisting fallback trigger (since webpack 3.0.0) | boolean -`--display-origins` | Display origins of chunks in the output | boolean -`--display-provided-exports` | Display information about exports provided from modules | boolean -`--display-reasons` | Display reasons about module inclusion in the output | boolean -`--display-used-exports` | Display information about used exports in modules (Tree Shaking) | boolean -`--hide-modules` | Hides info about modules | boolean -`--sort-assets-by` | Sorts the assets list by property in asset | string -`--sort-chunks-by` | Sorts the chunks list by property in chunk | string -`--sort-modules-by` | Sorts the modules list by property in module | string -`--verbose` | Show more details | boolean - - -### Advanced Options - -Parameter | Explanation | Usage ------------------ | ---------------------------------------- | ----- -`--bail` | Abort the compilation on first error | -`--cache` | Enable in memory caching [Enabled by default for watch] | `--cache=false` -`--define` | Define any free variable, see [shimming](/guides/shimming) | `--define process.env.NODE_ENV="'development'"` -`--hot` | Enables [Hot Module Replacement](/concepts/hot-module-replacement) | `--hot=true` -`--labeled-modules` | Enables labeled modules [Uses LabeledModulesPlugin] | -`--plugin` | Load this [plugin](/configuration/plugins/) | -`--prefetch` | Prefetch the particular file | `--prefetch=./files.js` -`--provide` | Provide these modules as globals, see [shimming](/guides/shimming) | `--provide jQuery=jquery` -`--records-input-path` | Path to the records file (reading) | -`--records-output-path` | Path to the records file (writing) | -`--records-path` | Path to the records file | -`--target` | The [targeted](/configuration/target/) execution environment | `--target='node'` - -### Shortcuts - -Shortcut | Replaces ----------|---------------------------- --d | `--debug --devtool cheap-module-eval-source-map --output-pathinfo` --p | `--optimize-minimize --define process.env.NODE_ENV="production"`, see [building for production](/guides/production) - -### Profiling - -The `--profile` option captures timing information for each step of the compilation and includes this in the output. - -```bash -webpack --profile - -⋮ -[0] ./src/index.js 90 bytes {0} [built] - factory:22ms building:16ms = 38ms -``` - -For each module, the following details are included in the output as applicable: - -- `factory`: time to collect module metadata (e.g. resolving the filename) -- `building`: time to build the module (e.g. loaders and parsing) -- `dependencies`: time to identify and connect the module’s dependencies - -Paired with `--progress`, `--profile` gives you an in depth idea of which step in the compilation is taking how long. This can help you optimise your build in a more informed manner. - -```bash -webpack --progress --profile - -30ms building modules -1ms sealing -1ms optimizing -0ms basic module optimization -1ms module optimization -1ms advanced module optimization -0ms basic chunk optimization -0ms chunk optimization -1ms advanced chunk optimization -0ms module and chunk tree optimization -1ms module reviving -0ms module order optimization -1ms module id optimization -1ms chunk reviving -0ms chunk order optimization -1ms chunk id optimization -10ms hashing -0ms module assets processing -13ms chunk assets processing -1ms additional chunk assets processing -0ms recording -0ms additional asset processing -26ms chunk asset optimization -1ms asset optimization -6ms emitting -⋮ -``` - - -# Compilation Hooks - -The `Compilation` module is used by the `Compiler` to create new compilations -(or builds). A `compilation` instance has access to all modules and their -dependencies (most of which are circular references). It is the literal -compilation of all the modules in the dependency graph of an application. -During the compilation phase, modules are loaded, sealed, optimized, chunked, -hashed and restored. - -The `Compilation` class also extends `Tapable` and provides the following -lifecycle hooks. They can be tapped the same way as compiler hooks: - -``` js -compilation.hooks.someHook.tap(/* ... */); -``` - -As with the `compiler`, `tapAsync` and `tapPromise` may also be available -depending on the type of hook. - - -### `buildModule` - -`SyncHook` - -Triggered before a module build has started. - -Parameters: `module` - - -### `rebuildModule` - -`SyncHook` - -Fired before rebuilding a module. - -Parameters: `module` - - -### `failedModule` - -`SyncHook` - -Run when a module build has failed. - -Parameters: `module` `error` - - -### `succeedModule` - -`SyncHook` - -Executed when a module has been built successfully. - -Parameters: `module` - - -### `finishModules` - -`SyncHook` - -All modules have been built. - -Parameters: `modules` - - -### `finishRebuildingModule` - -`SyncHook` - -A module has been rebuilt. - -Parameters: `module` - - -### `seal` - -`SyncHook` - -Fired when the compilation stops accepting new modules. - - -### `unseal` - -`SyncHook` - -Fired when a compilation begins accepting new modules. - - -### `optimizeDependenciesBasic` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeDependencies` - -`SyncBailHook` - -Fired at the beginning of dependency optimization. - -Parameters: `modules` - - -### `optimizeDependenciesAdvanced` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `afterOptimizeDependencies` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimize` - -`SyncHook` - -Triggered at the beginning of the optimization phase. - - -### `optimizeModulesBasic` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeModules` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `optimizeModulesAdvanced` - -`SyncBailHook` - -... - -Parameters: `modules` - - -### `afterOptimizeModules` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimizeChunksBasic` - -`SyncBailHook` - -... - -Parameters: `chunks` - - -### `optimizeChunks` - -`SyncBailHook` - -Optimize the chunks. - -Parameters: `chunks` - - -### `optimizeChunksAdvanced` - -`SyncBailHook` - -... - -Parameters: `chunks` - - -### `afterOptimizeChunks` - -`SyncHook` - -Fired after chunk optimization has completed. - -Parameters: `chunks` - - -### `optimizeTree` - -`AsyncSeriesHook` - -Optimize the dependency tree asynchronously. - -Parameters: `chunks` `modules` - - -### `afterOptimizeTree` - -`SyncHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModulesBasic` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModules` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `optimizeChunkModulesAdvanced` - -`SyncBailHook` - -... - -Parameters: `chunks` `modules` - - -### `afterOptimizeChunkModules` - -`SyncHook` - -... - -Parameters: `chunks` `modules` - - -### `shouldRecord` - -`SyncBailHook` - -... - - -### `reviveModules` - -`SyncHook` - -Restore module information from records. - -Parameters: `modules` `records` - - -### `optimizeModuleOrder` - -`SyncHook` - -Sort the modules in from most to least important. - -Parameters: `modules` - - -### `advancedOptimizeModuleOrder` - -`SyncHook` - -... - -Parameters: `modules` - - -### `beforeModuleIds` - -`SyncHook` - -... - -Parameters: `modules` - - -### `moduleIds` - -`SyncHook` - -... - -Parameters: `modules` - - -### `optimizeModuleIds` - -`SyncHook` - -... - -Parameters: `chunks` - - -### `afterOptimizeModuleIds` - -`SyncHook` - -... - -Parameters: `chunks` - - -### `reviveChunks` - -`SyncHook` - -Restore chunk information from records. - -Parameters: `modules` `records` - - -### `optimizeChunkOrder` - -`SyncHook` - -Sort the chunks in from most to least important. - -Parameters: `chunks` - - -### `beforeOptimizeChunkIds` - -`SyncHook` - -Fired before chunk `id` optimization. - -Parameters: `chunks` - - -### `optimizeChunkIds` - -`SyncHook` - -Optimize the `id` of each chunk. - -Parameters: `chunks` - - -### `afterOptimizeChunkIds` - -`SyncHook` - -Triggered after chunk `id` optimization has finished. - -Parameters: `chunks` - - -### `recordModules` - -`SyncHook` - -Store module info to the records. - -Parameters: `modules` `records` - - -### `recordChunks` - -`SyncHook` - -Store chunk info to the records. - -Parameters: `chunks` `records` - - -### `beforeHash` - -`SyncHook` - -Before the compilation is hashed. - - -### `afterHash` - -`SyncHook` - -After the compilation is hashed. - - -### `recordHash` - -`SyncHook` - -... - -Parameters: `records` - - -### `record` - -`SyncHook` - -Store information about the `compilation` to the `records`. - -Parameters: `compilation` `records` - - -### `beforeModuleAssets` - -`SyncHook` - -... - - -### `shouldGenerateChunkAssets` - -`SyncBailHook` - -... - - -### `beforeChunkAssets` - -`SyncHook` - -Before creating the chunk assets. - - -### `additionalChunkAssets` - -`SyncHook` - -Create additional assets for the chunks. - -Parameters: `chunks` - - -### `records` - -`SyncHook` - -... - -Parameters: `compilation` `records` - - -### `additionalAssets` - -`AsyncSeriesHook` - -Create additional assets for the compilation. This hook can be used to download -an image, for example: - -``` js -compilation.hooks.additionalAssets.tapAsync('MyPlugin', callback => { - download('https://img.shields.io/npm/v/webpack.svg', function(resp) { - if(resp.status === 200) { - compilation.assets['webpack-version.svg'] = toAsset(resp); - callback(); - } else { - callback(new Error('[webpack-example-plugin] Unable to download the image')); - } - }); -}); -``` - - -### `optimizeChunkAssets` - -`AsyncSeriesHook` - -Optimize any chunk assets. The assets are stored in `compilation.assets`. A -`Chunk` has a property `files` which points to all files created by a chunk. -Any additional chunk assets are stored in `compilation.additionalChunkAssets`. - -Parameters: `chunks` - -Here's an example that simply adds a banner to each chunk. - -``` js -compilation.hooks - .optimizeChunkAssets - .tapAsync('MyPlugin', (chunks, callback) => { - chunks.forEach(chunk => { - chunk.files.forEach(file => { - compilation.assets[file] = new ConcatSource( - '\/**Sweet Banner**\/', - '\n', - compilation.assets[file] - ); - }); - }); - - callback(); - }); -``` - - -### `afterOptimizeChunkAssets` - -`SyncHook` - -The chunk assets have been optimized. - -Parameters: `chunks` - -Here's an example plugin from [@boopathi](https://github.com/boopathi) that outputs exactly what went into each chunk. - -``` js -compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', chunks => { - chunks.forEach(chunk => { - console.log({ - id: chunk.id, - name: chunk.name, - includes: chunk.modules.map(module => module.request) - }); - }); -}); -``` - - -### `optimizeAssets` - -`AsyncSeriesHook` - -Optimize all assets stored in `compilation.assets`. - -Parameters: `assets` - - -### `afterOptimizeAssets` - -`SyncHook` - -The assets has been optimized. - -Parameters: `assets` - - -### `needAdditionalSeal` - -`SyncBailHook` - -... - - -### `afterSeal` - -`AsyncSeriesHook` - -... - - -### `chunkHash` - -`SyncHook` - -... - -Parameters: `chunk` `chunkHash` - - -### `moduleAsset` - -`SyncHook` - -An asset from a module was added to the compilation. - -Parameters: `module` `filename` - - -### `chunkAsset` - -`SyncHook` - -An asset from a chunk was added to the compilation. - -Parameters: `chunk` `filename` - - -### `assetPath` - -`SyncWaterfallHook` - -... - -Parameters: `filename` `data` - - -### `needAdditionalPass` - -`SyncBailHook` - -... - - -### `childCompiler` - -`SyncHook` - -... - -Parameters: `childCompiler` `compilerName` `compilerIndex` - - -### `normalModuleLoader` - -`SyncHook` - -The normal module loader is the function that actually loads all the modules -in the module graph (one-by-one). - -Parameters: `loaderContext` `module` - -### `dependencyReference` - -`SyncWaterfallHook` - -`Compilation.hooks.dependencyReference(depRef, dependency, module)` allows to change the references reported by dependencies. - -Parameters: `depRef` `dependency` `module` - - -# Module Methods - -This section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including [ES6](https://en.wikipedia.org/wiki/ECMAScript#6th_Edition_-_ECMAScript_2015), [CommonJS](https://en.wikipedia.org/wiki/CommonJS), and [AMD](https://en.wikipedia.org/wiki/Asynchronous_module_definition). - -W> While webpack supports multiple module syntaxes, we recommend following a single syntax for consistency and to avoid odd behaviors/bugs. Here's [one example](https://github.com/webpack/webpack.js.org/issues/552) of mixing ES6 and CommonJS, however there are surely others. - - -## ES6 (Recommended) - -Version 2 of webpack supports ES6 module syntax natively, meaning you can use `import` and `export` without a tool like babel to handle this for you. Keep in mind that you will still probably need babel for other ES6+ features. The following methods are supported by webpack: - - -### `import` - -Statically `import` the `export`s of another module. - -``` javascript -import MyModule from './my-module.js'; -import { NamedExport } from './other-module.js'; -``` - -W> The keyword here is __statically__. Normal `import` statement cannot be used dynamically within other logic or contain variables. See the [spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) for more information and `import()` below for dynamic usage. - - -### `export` - -Export anything as a `default` or named export. - -``` javascript -// Named exports -export var Count = 5; -export function Multiply(a, b) { - return a * b; -} - -// Default export -export default { - // Some data... -}; -``` - - -### `import()` - -`import('path/to/module') -> Promise` - -Dynamically load modules. Calls to `import()` are treated as split points, meaning the requested module and it's children are split out into a separate chunk. - -T> The [ES2015 Loader spec](https://whatwg.github.io/loader/) defines `import()` as method to load ES2015 modules dynamically on runtime. - -``` javascript -if ( module.hot ) { - import('lodash').then(_ => { - // Do something with lodash (a.k.a '_')... - }); -} -``` - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -The spec for `import` doesn't allow control over the chunk's name or other properties as "chunks" are only a concept within webpack. Luckily webpack allows some special parameters via comments so as to not break the spec: - -``` js -// Single target -import( - /* webpackChunkName: "my-chunk-name" */ - /* webpackMode: "lazy" */ - 'module' -); - -// Multiple possible targets -import( - /* webpackInclude: /\.json$/ */ - /* webpackExclude: /\.noimport\.json$/ */ - /* webpackChunkName: "my-chunk-name" */ - /* webpackMode: "lazy" */ - `./locale/${language}` -); -``` - -```js -import(/* webpackIgnore: true */ 'ignored-module.js'); -``` - -`webpackIgnore`: Disables dynamic import parsing when set to `true`. - -W> Note that setting `webpackIgnore` to `true` opts out of code splitting. - -`webpackChunkName`: A name for the new chunk. Since webpack 2.6.0, the placeholders `[index]` and `[request]` are supported within the given string to an incremented number or the actual resolved filename respectively. - -`webpackMode`: Since webpack 2.6.0, different modes for resolving dynamic imports can be specified. The following options are supported: - -- `"lazy"` (default): Generates a lazy-loadable chunk for each `import()`ed module. -- `"lazy-once"`: Generates a single lazy-loadable chunk that can satisfy all calls to `import()`. The chunk will be fetched on the first call to `import()`, and subsequent calls to `import()` will use the same network response. Note that this only makes sense in the case of a partially dynamic statement, e.g. ``import(`./locales/${language}.json`)``, where there are multiple module paths that could potentially be requested. -- `"eager"`: Generates no extra chunk. All modules are included in the current chunk and no additional network requests are made. A `Promise` is still returned but is already resolved. In contrast to a static import, the module isn't executed until the call to `import()` is made. -- `"weak"`: Tries to load the module if the module function has already been loaded in some other way (i. e. another chunk imported it or a script containing the module was loaded). A `Promise` is still returned but, only successfully resolves if the chunks are already on the client. If the module is not available, the `Promise` is rejected. A network request will never be performed. This is useful for universal rendering when required chunks are always manually served in initial requests (embedded within the page), but not in cases where app navigation will trigger an import not initially served. - -T> Note that all options can be combined like so `/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */`. This is wrapped in a JavaScript object and executed using [node VM](https://nodejs.org/dist/latest-v8.x/docs/api/vm.html). You do not need to add curly brackets. - -`webpackInclude`: A regular expression that will be matched against during import resolution. Only modules that match __will be bundled__. - -`webpackExclude`: A regular expression that will be matched against during import resolution. Any module that matches __will not be bundled__. - -T> Note that `webpackInclude` and `webpackExclude` options do not interfere with the prefix. eg: `./locale`. - -W> Fully dynamic statements, such as `import(foo)`, __will fail__ because webpack requires at least some file location information. This is because `foo` could potentially be any path to any file in your system or project. The `import()` must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files. - -W> Every module that could potentially be requested on an `import()` call is included. For example, ``import(`./locale/${language}.json`)`` will cause every `.json` file in the `./locale` directory to be bundled into the new chunk. At run time, when the variable `language` has been computed, any file like `english.json` or `german.json` will be available for consumption. Using the `webpackInclude` and `webpackExclude` options allows us to add regex patterns that reduce the files that webpack will bundle for this import. - -W> The use of `System.import` in webpack [did not fit the proposed spec](https://github.com/webpack/webpack/issues/2163), so it was deprecated in webpack [2.1.0-beta.28](https://github.com/webpack/webpack/releases/tag/v2.1.0-beta.28) in favor of `import()`. - - -## CommonJS - -The goal of CommonJS is to specify an ecosystem for JavaScript outside the browser. The following CommonJS methods are supported by webpack: - - -### `require` - -``` javascript -require(dependency: String); -``` - -Synchronously retrieve the exports from another module. The compiler will ensure that the dependency is available in the output bundle. - -``` javascript -var $ = require('jquery'); -var myModule = require('my-module'); -``` - -W> Using it asynchronously may not have the expected effect. - - -### `require.resolve` - -``` javascript -require.resolve(dependency: String); -``` - -Synchronously retrieve a module's ID. The compiler will ensure that the dependency is available in the output bundle. See [`module.id`](/api/module-variables#module-id-commonjs-) for more information. - -W> Module ID is a number in webpack (in contrast to NodeJS where it is a string -- the filename). - - -### `require.cache` - -Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. - -W> This is only needed in rare cases for compatibility! - -``` javascript -var d1 = require('dependency'); -require('dependency') === d1; -delete require.cache[require.resolve('dependency')]; -require('dependency') !== d1; -``` - -``` javascript -// in file.js -require.cache[module.id] === module; -require('./file.js') === module.exports; -delete require.cache[module.id]; -require.cache[module.id] === undefined; -require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow -require.cache[module.id] !== module; -``` - - -### `require.ensure` - -W> `require.ensure()` is specific to webpack and superseded by `import()`. - -<!-- eslint-skip --> - -```js -require.ensure( - dependencies: String[], - callback: function(require), - errorCallback: function(error), - chunkName: String -) -``` - -Split out the given `dependencies` to a separate bundle that that will be loaded asynchronously. When using CommonJS module syntax, this is the only way to dynamically load dependencies. Meaning, this code can be run within execution, only loading the `dependencies` if certain conditions are met. - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `require.ensure` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -``` javascript -var a = require('normal-dep'); - -if ( module.hot ) { - require.ensure(['b'], function(require) { - var c = require('c'); - - // Do something special... - }); -} -``` - -The following parameters are supported in the order specified above: - -- `dependencies`: An array of strings declaring all modules required for the code in the `callback` to execute. -- `callback`: A function that webpack will execute once the dependencies are loaded. An implementation of the `require` function is sent as a parameter to this function. The function body can use this to further `require()` modules it needs for execution. -- `errorCallback`: A function that is executed when webpack fails to load the dependencies. -- `chunkName`: A name given to the chunk created by this particular `require.ensure()`. By passing the same `chunkName` to various `require.ensure()` calls, we can combine their code into a single chunk, resulting in only one bundle that the browser must load. - -W> Although the implementation of `require` is passed as an argument to the `callback` function, using an arbitrary name e.g. `require.ensure([], function(request) { request('someModule'); })` isn't handled by webpack's static parser. Use `require` instead, e.g. `require.ensure([], function(require) { require('someModule'); })`. - - - -## AMD - -Asynchronous Module Definition (AMD) is a JavaScript specification that defines an interface for writing and loading modules. The following AMD methods are supported by webpack: - - -### `define` (with factory) - -<!-- eslint-skip --> - -```js -define([name: String], [dependencies: String[]], factoryMethod: function(...)) -``` - -If `dependencies` are provided, `factoryMethod` will be called with the exports of each dependency (in the same order). If `dependencies` are not provided, `factoryMethod` is called with `require`, `exports` and `module` (for compatibility!). If this function returns a value, this value is exported by the module. The compiler ensures that each dependency is available. - -W> Note that webpack ignores the `name` argument. - -``` javascript -define(['jquery', 'my-module'], function($, myModule) { - // Do something with $ and myModule... - - // Export a function - return function doSomething() { - // ... - }; -}); -``` - -W> This CANNOT be used in an asynchronous function. - - -### `define` (with value) - -<!-- eslint-skip --> - -```js -define(value: !Function) -``` - -This will simply export the provided `value`. The `value` here can be anything except a function. - -``` javascript -define({ - answer: 42 -}); -``` - -W> This CANNOT be used in an async function. - - -### `require` (amd-version) - -<!-- eslint-skip --> - -```js -require(dependencies: String[], [callback: function(...)]) -``` - -Similar to `require.ensure`, this will split the given `dependencies` into a separate bundle that will be loaded asynchronously. The `callback` will be called with the exports of each dependency in the `dependencies` array. - -W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use AMD with older browsers (e.g. Internet Explorer 11), remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -``` javascript -require(['b'], function(b) { - var c = require('c'); -}); -``` - -W> There is no option to provide a chunk name. - - - -## Labeled Modules - -The internal `LabeledModulesPlugin` enables you to use the following methods for exporting and requiring within your modules: - - -### `export` label - -Export the given `value`. The label can occur before a function declaration or a variable declaration. The function name or variable name is the identifier under which the value is exported. - -<!-- eslint-skip --> - -```js -export: var answer = 42; -export: function method(value) { - // Do something... -}; -``` - -W> Using it in an async function may not have the expected effect. - - -### `require` label - -Make all exports from the dependency available in the current scope. The `require` label can occur before a string. The dependency must export values with the `export` label. CommonJS or AMD modules cannot be consumed. - -__some-dependency.js__ - -<!-- eslint-skip --> - -```js -export: var answer = 42; -export: function method(value) { - // Do something... -}; -``` - -<!-- eslint-skip --> - -```js -require: 'some-dependency'; -console.log(answer); -method(...); -``` - - - -## Webpack - -Aside from the module syntaxes described above, webpack also allows a few custom, webpack-specific methods: - - -### `require.context` - -<!-- eslint-skip --> - -```js -require.context( - directory: String, - includeSubdirs: Boolean /* optional, default true */, - filter: RegExp /* optional, default /^\.\/.*$/, any file */, - mode: String /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */ -) -``` - -Specify a whole group of dependencies using a path to the `directory`, an option to `includeSubdirs`, a `filter` for more fine grained control of the modules included, and a `mode` to define the way how loading will work. Underlying modules can then be easily resolved later on: - -```javascript -var context = require.context('components', true, /\.html$/); -var componentA = context.resolve('componentA'); -``` - -If `mode` is specified as "lazy", the underlying modules will be loaded asynchronously: - -```javascript -var context = require.context('locales', true, /\.json$/, 'lazy'); -context('localeA').then(locale => { - // do something with locale -}); -``` - -The full list of available modes and its behavior is described in [`import()`](#import-) documentation. - -### `require.include` - -<!-- eslint-skip --> - -```js -require.include(dependency: String) -``` - -Include a `dependency` without executing it. This can be used for optimizing the position of a module in the output chunks. - -``` javascript -require.include('a'); -require.ensure(['a', 'b'], function(require) { /* ... */ }); -require.ensure(['a', 'c'], function(require) { /* ... */ }); -``` - -This will result in following output: - -- entry chunk: `file.js` and `a` -- anonymous chunk: `b` -- anonymous chunk: `c` - -Without `require.include('a')` it would be duplicated in both anonymous chunks. - - -### `require.resolveWeak` - -Similar to `require.resolve`, but this won't pull the `module` into the bundle. It's what is considered a "weak" dependency. - -``` javascript -if(__webpack_modules__[require.resolveWeak('module')]) { - // Do something when module is available... -} -if(require.cache[require.resolveWeak('module')]) { - // Do something when module was loaded before... -} - -// You can perform dynamic resolves ("context") -// just as with other require/import methods. -const page = 'Foo'; -__webpack_modules__[require.resolveWeak(`./page/${page}`)]; -``` - -T> `require.resolveWeak` is the foundation of _universal rendering_ (SSR + Code Splitting), as used in packages such as [react-universal-component](https://github.com/faceyspacey/react-universal-component). It allows code to render synchronously on both the server and initial page-loads on the client. It requires that chunks are manually served or somehow available. It's able to require modules without indicating they should be bundled into a chunk. It's used in conjunction with `import()` which takes over when user navigation triggers additional imports. - - -# Node.js API - -webpack provides a Node.js API which can be used directly in Node.js runtime. - -The Node.js API is useful in scenarios in which you need to customize the build or development process since all the reporting and error handling must be done manually and webpack only does the compiling part. For this reason the [`stats`](/configuration/stats) configuration options will not have any effect in the `webpack()` call. - - -## Installation - -To start using webpack Node.js API, first install webpack if you haven’t yet: - -``` bash -npm install --save-dev webpack -``` - -Then require the webpack module in your Node.js script: - -``` js -const webpack = require('webpack'); -``` - -Or if you prefer ES2015: - -``` js -import webpack from 'webpack'; -``` - - -## `webpack()` - -The imported `webpack` function is fed a webpack [Configuration Object](/configuration/) and runs the webpack compiler if a callback function is provided: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, [stats](#stats-object)) => { - if (err || stats.hasErrors()) { - // [Handle errors here](#error-handling) - } - // Done processing -}); -``` - -T> The `err` object __will not__ include compilation errors and those must be handled separately using `stats.hasErrors()` which will be covered in detail in [Error Handling](#error-handling) section of this guide. The `err` object will only contain webpack-related issues, such as misconfiguration, etc. - -T> You can provide the `webpack` function with an array of configurations. See -the [MultiCompiler](#multicompiler) section below for more information. - - -## Compiler Instance - -If you don’t pass the `webpack` runner function a callback, it will return a -webpack `Compiler` instance. This instance can be used to manually trigger the -webpack runner or have it build and watch for changes, much like the -[CLI](/api/cli/). The `Compiler` instance provides the following methods: - -- `.run(callback)` -- `.watch(watchOptions, handler)` - -Typically, only one master `Compiler` instance is created, although child -compilers can be created in order to delegate specific tasks. The `Compiler` is -ultimately just a function which performs bare minimum functionality to keep a -lifecycle running. It delegates all the loading, bundling, and writing work to -registered plugins. - -The `hooks` property on a `Compiler` instance is used to register a plugin to -any hook event in the `Compiler`'s lifecycle. The -[`WebpackOptionsDefaulter`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js) -and [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js) -utilities are used by webpack to configure its `Compiler` instance with all the -built-in plugins. - -The `run` method is then used to kickstart all compilation work. Upon -completion, the given `callback` function is executed. The final logging of -stats and errors should be done in this `callback` function. - -W> The API only supports a single concurrent compilation at a time. When using -`run`, wait for it to finish before calling `run` or `watch` again. When using -`watch`, call `close` and wait for it to finish before calling `run` or `watch` -again. Concurrent compilations will corrupt the output files. - - -## Run - -Calling the `run` method on the `Compiler` instance is much like the quick run -method mentioned above: - -``` js-with-links -const webpack = require("webpack"); - -const compiler = webpack({ - // [Configuration Object](/configuration/) -}); - -compiler.run((err, [stats](#stats-object)) => { - // ... -}); -``` - - -## Watching - -Calling the `watch` method, triggers the webpack runner, but then watches for -changes (much like CLI: `webpack --watch`), as soon as webpack detects a -change, runs again. Returns an instance of `Watching`. - -``` js -watch(watchOptions, callback); -``` - -``` js-with-links -const webpack = require("webpack"); - -const compiler = webpack({ - // [Configuration Object](/configuration/) -}); - -const watching = compiler.watch({ - // Example [watchOptions](/configuration/watch/#watchoptions) - aggregateTimeout: 300, - poll: undefined -}, (err, [stats](#stats-object)) => { - // Print watch/build result here... - console.log(stats); -}); -``` - -`Watching` options are covered in detail -[here](/configuration/watch/#watchoptions). - -W> Filesystem inaccuracies may trigger multiple builds for a single change. So, -in the example above, the `console.log` statement may fire multiple times for a -single modification. Users should expect this behavior and may check -`stats.hash` to see if the file hash has actually changed. - - -### Close `Watching` - -The `watch` method returns a `Watching` instance that exposes -`.close(callback)` method. Calling this method will end watching: - -``` js -watching.close(() => { - console.log('Watching Ended.'); -}); -``` - -W> It’s not allowed to watch or run again before the existing watcher has been -closed or invalidated. - - -### Invalidate `Watching` - -Using `watching.invalidate`, you can manually invalidate the current compiling -round, without stopping the watch process: - -``` js -watching.invalidate(); -``` - - -## Stats Object - -The `stats` object that is passed as a second argument of the -[`webpack()`](#webpack-) callback, is a good source of information about the -code compilation process. It includes: - -- Errors and Warnings (if any) -- Timings -- Module and Chunk information - -The [webpack CLI](/api/cli) uses this information to display nicely formatted -output in your console. - -T> When using the [`MultiCompiler`](/api/plugins/compiler#multicompiler), a -`MultiStats` instance is returned that fulfills the same interface as `stats`, -i.e. the methods described below. - -This `stats` object exposes the following methods: - - -### `stats.hasErrors()` - -Can be used to check if there were errors while compiling. Returns `true` or -`false`. - - -### `stats.hasWarnings()` - -Can be used to check if there were warnings while compiling. Returns `true` or -`false`. - - -### `stats.toJson(options)` - -Returns compilation information as a JSON object. `options` can be either a -string (a preset) or an object for more granular control: - -``` js-with-links -stats.toJson("minimal"); // [more options: "verbose", etc](/configuration/stats). -``` - -``` js -stats.toJson({ - assets: false, - hash: true -}); -``` - -All available options and presets are described in the stats [documentation](/configuration/stats). - -> Here’s an [example] -(https://github.com/webpack/analyse/blob/master/app/pages/upload/example.json) -of this function’s output. - - -### `stats.toString(options)` - -Returns a formatted string of the compilation information (similar to -[CLI](/api/cli) output). - -Options are the same as [`stats.toJson(options)`](/api/node#stats-tojson-options-) with one addition: - -``` js -stats.toString({ - // Add console colors - colors: true -}); -``` - -Here’s an example of `stats.toString()` usage: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, stats) => { - if (err) { - console.error(err); - return; - } - - console.log(stats.toString({ - chunks: false, // Makes the build much quieter - colors: true // Shows colors in the console - })); -}); -``` - - -## MultiCompiler - -The `MultiCompiler` module allows webpack to run multiple configurations in -separate compilers. If the `options` parameter in the webpack's NodeJS api is -an array of options, webpack applies separate compilers and calls the -`callback` method at the end of each compiler execution. - -``` js-with-links -var webpack = require('webpack'); - -webpack([ - { entry: './index1.js', output: { filename: 'bundle1.js' } }, - { entry: './index2.js', output: { filename: 'bundle2.js' } } -], (err, [stats](#stats-object)) => { - process.stdout.write(stats.toString() + "\n"); -}) -``` - -W> Multiple configurations will __not be run in parallel__. Each -configuration is only processed after the previous one has finished -processing. To process them in parallel, you can use a third-party solution -like [parallel-webpack](https://www.npmjs.com/package/parallel-webpack). - - -## Error Handling - -For a good error handling, you need to account for these three types of errors: - -- Fatal webpack errors (wrong configuration, etc) -- Compilation errors (missing modules, syntax errors, etc) -- Compilation warnings - -Here’s an example that does all that: - -``` js-with-links -const webpack = require("webpack"); - -webpack({ - // [Configuration Object](/configuration/) -}, (err, stats) => { - if (err) { - console.error(err.stack || err); - if (err.details) { - console.error(err.details); - } - return; - } - - const info = stats.toJson(); - - if (stats.hasErrors()) { - console.error(info.errors); - } - - if (stats.hasWarnings()) { - console.warn(info.warnings); - } - - // Log result... -}); -``` - - -## Custom File Systems - -By default, webpack reads files and writes files to disk using a normal file -system. However, it is possible to change the input or output behavior using a -different kind of file system (memory, webDAV, etc). To accomplish this, one -can change the `inputFileSystem` or `outputFileSystem`. For example, you can -replace the default `outputFileSystem` with -[`memory-fs`](https://github.com/webpack/memory-fs) to write files to memory -instead of to disk: - -``` js -const MemoryFS = require('memory-fs'); -const webpack = require('webpack'); - -const fs = new MemoryFS(); -const compiler = webpack({ /* options*/ }); - -compiler.outputFileSystem = fs; -compiler.run((err, stats) => { - // Read the output later: - const content = fs.readFileSync('...'); -}); -``` - -Note that this is what -[webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware), -used by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) -and many other packages, uses to mysteriously hide your files but continue -serving them up to the browser! - -T> The output file system you provide needs to be compatible with Node’s own -[`fs`](https://nodejs.org/api/fs.html) interface, which requires the `mkdirp` -and `join` helper methods. - - -# Resolvers - -Resolvers are created using the `enhanced-resolve` package. The `Resolver` -class extends the `tapable` class and uses `tapable` to provide a few hooks. -The `enhanced-resolve` package can be used directly to create new resolvers, -however any [`compiler` instance](/api/node/#compiler-instance) has a few resolver instances that can be -tapped into. - -Before reading on, make sure you at least skim through the -[`enhanced-resolve`](https://github.com/webpack/enhanced-resolve) and [`tapable`](/api/plugins/#tapable) documentation. - - -## Types - -There are three types of built-in resolvers available on the `compiler` class: - -- Normal: Resolves a module via an absolute or relative path. -- Context: Resolves a module within a given context. -- Loader: Resolves a webpack [loader](/loaders). - -Depending on need, any one of these built-in resolver used by the `compiler` -can be customized via plugins as such: - -``` js -compiler.resolverFactory.plugin('resolver [type]', resolver => { - resolver.hooks.resolve.tapAsync('MyPlugin', params => { - // ... - }); -}); -``` - -Where `[type]` is one of the three resolvers mention above, specified as: - -- `normal` -- `context` -- `loader` - - -See the `enhanced-resolve` [documentation](https://github.com/webpack/enhanced-resolve) for a full list of hooks and -descriptions. - - -## Configuration Options - -The resolvers mentioned above can also be customized via a configuration file -with the [`resolve`](/configuration/resolve/) or [`resolveLoader`](/configuration/resolve/#resolveloader) options. These options allow -users to change the resolving behavior through a variety of options including -through resolve `plugins`. - -The resolver plugins, e.g. [`DirectoryNamedPlugin`](https://github.com/shaketbaby/directory-named-webpack-plugin), can be included -directly in `resolve.plugins` rather than using standard plugins. Note that the -`resolve` configuration affects the `normal` and `context` resolvers while -`resolveLoader` is used to modify the `loader` resolver. - - -# Stats Data - -When compiling source code with webpack, users can generate a JSON file containing statistics about modules. These statistics can be used to analyze an application's dependency graph as well as to optimize compilation speed. The file is typically generated with the following CLI command: - -``` bash -webpack --profile --json > compilation-stats.json -``` - -The `--json > compilation-stats.json` flag indicates to webpack that it should emit the `compilation-stats.json` containing the dependency graph and various other build information. Typically, the `--profile` flag is also added so that a `profile` section is added to each [`modules` object](#module-objects) containing module-specific compilation stats. - - -## Structure - -The top-level structure of the output JSON file is fairly straightforward but there are a few nested data structures as well. Each nested structure has a dedicated section below to make this document more consumable. Note that you can click links within the top-level structure below to jump to relevant sections and documentation: - -```js-with-links -{ - "version": "1.4.13", // Version of webpack used for the compilation - "hash": "11593e3b3ac85436984a", // Compilation specific hash - "time": 2469, // Compilation time in milliseconds - "filteredModules": 0, // A count of excluded modules when [`exclude`](/configuration/stats/#stats) is passed to the [`toJson`](/api/node/#stats-tojson-options-) method - "outputPath": "/", // path to webpack output directory - "assetsByChunkName": { - // Chunk name to emitted asset(s) mapping - "main": "web.js?h=11593e3b3ac85436984a", - "named-chunk": "named-chunk.web.js", - "other-chunk": [ - "other-chunk.js", - "other-chunk.css" - ] - }, - "assets": [ - // A list of [asset objects](#asset-objects) - ], - "chunks": [ - // A list of [chunk objects](#chunk-objects) - ], - "modules": [ - // A list of [module objects](#module-objects) - ], - "errors": [ - // A list of [error strings](#errors-and-warnings) - ], - "warnings": [ - // A list of [warning strings](#errors-and-warnings) - ] -} -``` - - -### Asset Objects - -Each `assets` object represents an `output` file emitted from the compilation. They all follow a similar structure: - -<!-- eslint-skip --> - -```js -{ - "chunkNames": [], // The chunks this asset contains - "chunks": [ 10, 6 ], // The chunk IDs this asset contains - "emitted": true, // Indicates whether or not the asset made it to the `output` directory - "name": "10.web.js", // The `output` filename - "size": 1058 // The size of the file in bytes -} -``` - - -### Chunk Objects - -Each `chunks` object represents a group of modules known as a [chunk](/glossary#c). Each object follows the following structure: - -```js-with-links -{ - "entry": true, // Indicates whether or not the chunk contains the webpack runtime - "files": [ - // An array of filename strings that contain this chunk - ], - "filteredModules": 0, // See the description in the [top-level structure](#structure) above - "id": 0, // The ID of this chunk - "initial": true, // Indicates whether this chunk is loaded on initial page load or [on demand](/guides/lazy-loading) - "modules": [ - // A list of [module objects](#module-objects) - "web.js?h=11593e3b3ac85436984a" - ], - "names": [ - // An list of chunk names contained within this chunk - ], - "origins": [ - // See the description below... - ], - "parents": [], // Parent chunk IDs - "rendered": true, // Indicates whether or not the chunk went through Code Generation - "size": 188057 // Chunk size in bytes -} -``` - -The `chunks` object will also contain a list of `origins` describing how the given chunk originated. Each `origins` object follows the following schema: - -```js-with-links -{ - "loc": "", // Lines of code that generated this chunk - "module": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleId": 0, // The ID of the module - "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleName": "./lib/index.web.js", // Relative path to the module - "name": "main", // The name of the chunk - "reasons": [ - // A list of the same `reasons` found in [module objects](#module-objects) - ] -} -``` - - -### Module Objects - -What good would these statistics be without some description of the compiled application's actual modules? Each module in the dependency graph is represented by the following structure: - -```js-with-links -{ - "assets": [ - // A list of [asset objects](#asset-objects) - ], - "built": true, // Indicates that the module went through [Loaders](/concepts/loaders), Parsing, and Code Generation - "cacheable": true, // Whether or not this module is cacheable - "chunks": [ - // IDs of chunks that contain this module - ], - "errors": 0, // Number of errors when resolving or processing the module - "failed": false, // Whether or not compilation failed on this module - "id": 0, // The ID of the module (analagous to [`module.id`](/api/module-variables#module-id-commonjs-)) - "identifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // A unique ID used internally - "name": "./lib/index.web.js", // Path to the actual file - "optional": false, // All requests to this module are with `try... catch` blocks (irrelevant with ESM) - "prefetched": false, // Indicates whether or not the module was [prefetched](/plugins/prefetch-plugin) - "profile": { - // Module specific compilation stats corresponding to the [`--profile` flag](/api/cli#profiling) (in milliseconds) - "building": 73, // Loading and parsing - "dependencies": 242, // Building dependencies - "factory": 11 // Resolving dependencies - }, - "reasons": [ - // See the description below... - ], - "size": 3593, // Estimated size of the module in bytes - "source": "// Should not break it...\r\nif(typeof...", // The stringified raw source - "warnings": 0 // Number of warnings when resolving or processing the module -} -``` - -Every module also contains a list of `reasons` objects describing why that module was included in the dependency graph. Each "reason" is similar to the `origins` seen above in the [chunk objects](#chunk-objects) section: - -```js-with-links -{ - "loc": "33:24-93", // Lines of code that caused the module to be included - "module": "./lib/index.web.js", // Relative path to the module based on [context](/configuration/entry-context/#context) - "moduleId": 0, // The ID of the module - "moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // Path to the module - "moduleName": "./lib/index.web.js", // A more readable name for the module (used for "pretty-printing") - "type": "require.context", // The [type of request](/api/module-methods) used - "userRequest": "../../cases" // Raw string used for the `import` or `require` request -} -``` - - -### Errors and Warnings - -The `errors` and `warnings` properties each contain a list of strings. Each string contains a message and stack trace: - -``` bash -../cases/parsing/browserify/index.js -Critical dependencies: -2:114-121 This seem to be a pre-built javascript file. Even while this is possible, it's not recommended. Try to require to original source to get better results. - @ ../cases/parsing/browserify/index.js 2:114-121 -``` - -W> Note that the stack traces are removed when `errorDetails: false` is passed to the `toJson` method. The `errorDetails` option is set to `true` by default. - - -# Loader API - -A loader is just a JavaScript module that exports a function. The [loader runner](https://github.com/webpack/loader-runner) calls this function and passes the result of the previous loader or the resource file into it. The `this` context of the function is filled-in by webpack and the [loader runner](https://github.com/webpack/loader-runner) with some useful methods that allow the loader (among other things) to change its invocation style to async, or get query parameters. - -The first loader is passed one argument: the content of the resource file. The compiler expects a result from the last loader. The result should be a `String` or a `Buffer` (which is converted to a string), representing the JavaScript source code of the module. An optional SourceMap result (as JSON object) may also be passed. - -A single result can be returned in __sync mode__. For multiple results the `this.callback()` must be called. In __async mode__ `this.async()` must be called to indicate that the [loader runner](https://github.com/webpack/loader-runner) should wait for an asynchronous result. It returns `this.callback()`. Then the loader must return `undefined` and call that callback. - - -## Examples - -The following sections provide some basic examples of the different types of loaders. Note that the `map` and `meta` parameters are optional, see [`this.callback`](/api/loaders#this-callback) below. - -### Synchronous Loaders - -Either `return` or `this.callback` can be used to return the transformed `content` synchronously: - -__sync-loader.js__ - -``` js -module.exports = function(content, map, meta) { - return someSyncOperation(content); -}; -``` - -The `this.callback` method is more flexible as it allows multiple arguments to be passed as opposed to just the `content`. - -__sync-loader-with-multiple-results.js__ - -``` js -module.exports = function(content, map, meta) { - this.callback(null, someSyncOperation(content), map, meta); - return; // always return undefined when calling callback() -}; -``` - -### Asynchronous Loaders - -For asynchronous loaders, [`this.async`](/api/loaders#this-async) is used to retrieve the `callback` function: - -__async-loader.js__ - -``` js -module.exports = function(content, map, meta) { - var callback = this.async(); - someAsyncOperation(content, function(err, result) { - if (err) return callback(err); - callback(null, result, map, meta); - }); -}; -``` - -__async-loader-with-multiple-results.js__ - -``` js -module.exports = function(content, map, meta) { - var callback = this.async(); - someAsyncOperation(content, function(err, result, sourceMaps, meta) { - if (err) return callback(err); - callback(null, result, sourceMaps, meta); - }); -}; -``` - -T> Loaders were originally designed to work in synchronous loader pipelines, like Node.js (using [enhanced-require](https://github.com/webpack/enhanced-require)), _and_ asynchronous pipelines, like in webpack. However, since expensive synchronous computations are a bad idea in a single-threaded environment like Node.js, we advise to make your loader asynchronously if possible. Synchronous loaders are ok if the amount of computation is trivial. - - -### "Raw" Loader - -By default, the resource file is converted to a UTF-8 string and passed to the loader. By setting the `raw` flag, the loader will receive the raw `Buffer`. Every loader is allowed to deliver its result as `String` or as `Buffer`. The compiler converts them between loaders. - -__raw-loader.js__ - -``` js -module.exports = function(content) { - assert(content instanceof Buffer); - return someSyncOperation(content); - // return value can be a `Buffer` too - // This is also allowed if loader is not "raw" -}; -module.exports.raw = true; -``` - - -### Pitching Loader - -Loaders are __always__ called from right to left. There are some instances where the loader only cares about the __metadata__ behind a request and can ignore the results of the previous loader. The `pitch` method on loaders is called from __left to right__ before the loaders are actually executed (from right to left). For the following [`use`](/configuration/module#rule-use) configuration: - -``` js -module.exports = { - //... - module: { - rules: [ - { - //... - use: [ - 'a-loader', - 'b-loader', - 'c-loader' - ] - } - ] - } -}; -``` - -These steps would occur: - -``` diff -|- a-loader `pitch` - |- b-loader `pitch` - |- c-loader `pitch` - |- requested module is picked up as a dependency - |- c-loader normal execution - |- b-loader normal execution -|- a-loader normal execution -``` - -So why might a loader take advantage of the "pitching" phase? - -First, the `data` passed to the `pitch` method is exposed in the execution phase as well under `this.data` and could be useful for capturing and sharing information from earlier in the cycle. - -``` js -module.exports = function(content) { - return someSyncOperation(content, this.data.value); -}; - -module.exports.pitch = function(remainingRequest, precedingRequest, data) { - data.value = 42; -}; -``` - -Second, if a loader delivers a result in the `pitch` method the process turns around and skips the remaining loaders. In our example above, if the `b-loader`s `pitch` method returned something: - -``` js -module.exports = function(content) { - return someSyncOperation(content); -}; - -module.exports.pitch = function(remainingRequest, precedingRequest, data) { - if (someCondition()) { - return 'module.exports = require(' + JSON.stringify('-!' + remainingRequest) + ');'; - } -}; -``` - -The steps above would be shortened to: - -``` diff -|- a-loader `pitch` - |- b-loader `pitch` returns a module -|- a-loader normal execution -``` - -See the [bundle-loader](https://github.com/webpack-contrib/bundle-loader) for a good example of how this process can be used in a more meaningful way. - - -## The Loader Context - -The loader context represents the properties that are available inside of a loader assigned to the `this` property. - -Given the following example this require call is used: -In `/abc/file.js`: - -``` js -require('./loader1?xyz!loader2!./resource?rrr'); -``` - - -### `this.version` - -__Loader API version.__ Currently `2`. This is useful for providing backwards compatibility. Using the version you can specify custom logic or fallbacks for breaking changes. - - -### `this.context` - -__The directory of the module.__ Can be used as context for resolving other stuff. - -In the example: `/abc` because `resource.js` is in this directory - - -### `this.rootContext` - -Starting with webpack 4, the formerly `this.options.context` is provided as `this.rootContext`. - - -### `this.request` - -The resolved request string. - -In the example: `"/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"` - - -### `this.query` - -1. If the loader was configured with an [`options`](/configuration/module/#useentry) object, this will point to that object. -2. If the loader has no `options`, but was invoked with a query string, this will be a string starting with `?`. - -T> Use the [`getOptions` method](https://github.com/webpack/loader-utils#getoptions) from `loader-utils` to extract given loader options. - - -### `this.callback` - -A function that can be called synchronously or asynchronously in order to return multiple results. The expected arguments are: - -<!-- eslint-skip --> - -```js -this.callback( - err: Error | null, - content: string | Buffer, - sourceMap?: SourceMap, - meta?: any -); -``` - -1. The first argument must be an `Error` or `null` -2. The second argument a `string` or a [`Buffer`](https://nodejs.org/api/buffer.html). -3. Optional: The third argument must be a source map that is parsable by [this module](https://github.com/mozilla/source-map). -4. Optional: The fourth option, ignored by webpack, can be anything (e.g. some meta data). - -T> It can be useful to pass an abstract syntax tree (AST), like [`ESTree`](https://github.com/estree/estree), as the fourth argument (`meta`) to speed up the build time if you want to share common ASTs between loaders. - -In case this function is called, you should return undefined to avoid ambiguous loader results. - - -### `this.async` - -Tells the [loader-runner](https://github.com/webpack/loader-runner) that the loader intends to call back asynchronously. Returns `this.callback`. - - -### `this.data` - -A data object shared between the pitch and the normal phase. - - -### `this.cacheable` - -A function that sets the cacheable flag: - -``` typescript -cacheable(flag = true: boolean) -``` - -By default, loader results are flagged as cacheable. Call this method passing `false` to make the loader's result not cacheable. - -A cacheable loader must have a deterministic result, when inputs and dependencies haven't changed. This means the loader shouldn't have other dependencies than specified with `this.addDependency`. - - -### `this.loaders` - -An array of all the loaders. It is writeable in the pitch phase. - -<!-- eslint-skip --> - -```js -loaders = [{request: string, path: string, query: string, module: function}] -``` - -In the example: - -``` js -[ - { - request: '/abc/loader1.js?xyz', - path: '/abc/loader1.js', - query: '?xyz', - module: [Function] - }, - { - request: '/abc/node_modules/loader2/index.js', - path: '/abc/node_modules/loader2/index.js', - query: '', - module: [Function] - } -]; -``` - - -### `this.loaderIndex` - -The index in the loaders array of the current loader. - -In the example: in loader1: `0`, in loader2: `1` - - -### `this.resource` - -The resource part of the request, including query. - -In the example: `"/abc/resource.js?rrr"` - - -### `this.resourcePath` - -The resource file. - -In the example: `"/abc/resource.js"` - - -### `this.resourceQuery` - -The query of the resource. - -In the example: `"?rrr"` - - -### `this.target` - -Target of compilation. Passed from configuration options. - -Example values: `"web"`, `"node"` - - -### `this.webpack` - -This boolean is set to true when this is compiled by webpack. - -T> Loaders were originally designed to also work as Babel transforms. Therefore if you write a loader that works for both, you can use this property to know if there is access to additional loaderContext and webpack features. - - -### `this.sourceMap` - -Should a source map be generated. Since generating source maps can be an expensive task, you should check if source maps are actually requested. - - -### `this.emitWarning` - -``` typescript -emitWarning(warning: Error) -``` - -Emit a warning. - - -### `this.emitError` - -``` typescript -emitError(error: Error) -``` - -Emit an error. - - -### `this.loadModule` - -``` typescript -loadModule(request: string, callback: function(err, source, sourceMap, module)) -``` - -Resolves the given request to a module, applies all configured loaders and calls back with the generated source, the sourceMap and the module instance (usually an instance of [`NormalModule`](https://github.com/webpack/webpack/blob/master/lib/NormalModule.js)). Use this function if you need to know the source code of another module to generate the result. - - -### `this.resolve` - -``` typescript -resolve(context: string, request: string, callback: function(err, result: string)) -``` - -Resolve a request like a require expression. - - -### `this.addDependency` - -``` typescript -addDependency(file: string) -dependency(file: string) // shortcut -``` - -Adds a file as dependency of the loader result in order to make them watchable. For example, [`html-loader`](https://github.com/webpack-contrib/html-loader) uses this technique as it finds `src` and `src-set` attributes. Then, it sets the url's for those attributes as dependencies of the html file that is parsed. - - -### `this.addContextDependency` - -``` typescript -addContextDependency(directory: string) -``` - -Add a directory as dependency of the loader result. - - -### `this.clearDependencies` - -``` typescript -clearDependencies() -``` - -Remove all dependencies of the loader result. Even initial dependencies and these of other loaders. Consider using `pitch`. - - -### `this.emitFile` - -``` typescript -emitFile(name: string, content: Buffer|string, sourceMap: {...}) -``` - -Emit a file. This is webpack-specific. - - -### `this.fs` - -Access to the `compilation`'s `inputFileSystem` property. - - -## Deprecated context properties - -W> The usage of these properties is highly discouraged since we are planning to remove them from the context. They are still listed here for documentation purposes. - - -### `this.exec` - -``` typescript -exec(code: string, filename: string) -``` - -Execute some code fragment like a module. See [this comment](https://github.com/webpack/webpack.js.org/issues/1268#issuecomment-313513988) for a replacement method if needed. - - -### `this.resolveSync` - -``` typescript -resolveSync(context: string, request: string) -> string -``` - -Resolve a request like a require expression. - - -### `this.value` - -Pass values to the next loader. If you know what your result exports if executed as module, set this value here (as a only element array). - - -### `this.inputValue` - -Passed from the last loader. If you would execute the input argument as module, consider reading this variable for a shortcut (for performance). - - -### `this.options` - -W> The `options` property has been deprecated in webpack 3 and removed in webpack 4. - - -### `this.debug` - -A boolean flag. It is set when in debug mode. - - -### `this.minimize` - -Should the result be minimized. - - -### `this._compilation` - -Hacky access to the Compilation object of webpack. - - -### `this._compiler` - -Hacky access to the Compiler object of webpack. - - -### `this._module` - -Hacky access to the Module object being loaded. - - -# Module Variables - -This section covers all __variables__ available in code compiled with webpack. Modules will have access to certain data from the compilation process through `module` and other variables. - - -### `module.loaded` (NodeJS) - -This is `false` if the module is currently executing, and `true` if the sync execution has finished. - - -### `module.hot` (webpack-specific) - -Indicates whether or not [Hot Module Replacement](/concepts/hot-module-replacement) is enabled and provides an interface to the process. See the [HMR API page](/api/hot-module-replacement) for details. - - -### `module.id` (CommonJS) - -The ID of the current module. - -``` javascript -module.id === require.resolve('./file.js'); -``` - - -### `module.exports` (CommonJS) - -Defines the value that will be returned when a consumer makes a `require` call to the module (defaults to a new object). - -``` javascript -module.exports = function doSomething() { - // Do something... -}; -``` - -W> This CANNOT be used in an asynchronous function. - - -### `exports` (CommonJS) - -This variable is equal to default value of `module.exports` (i.e. an object). If `module.exports` gets overwritten, `exports` will no longer be exported. - -``` javascript -exports.someValue = 42; -exports.anObject = { - x: 123 -}; -exports.aFunction = function doSomething() { - // Do something -}; -``` - - -### `global` (NodeJS) - -See [node.js global](https://nodejs.org/api/globals.html#globals_global). - - -### `process` (NodeJS) - -See [node.js process](https://nodejs.org/api/process.html). - - -### `__dirname` (NodeJS) - -Depending on the config option `node.__dirname`: - -- `false`: Not defined -- `mock`: equal "/" -- `true`: [node.js __dirname](https://nodejs.org/api/globals.html#globals_dirname) - -If used inside a expression that is parsed by the Parser, the config option is treated as `true`. - - -### `__filename` (NodeJS) - -Depending on the config option `node.__filename`: - -- `false`: Not defined -- `mock`: equal "/index.js" -- `true`: [node.js __filename](https://nodejs.org/api/globals.html#globals_filename) - -If used inside a expression that is parsed by the Parser, the config option is treated as `true`. - - -### `__resourceQuery` (webpack-specific) - -The resource query of the current module. If the following `require` call were made, then the query string would be available in `file.js`. - -``` javascript -require('file.js?test'); -``` - -__file.js__ - -``` javascript -__resourceQuery === '?test'; -``` - - -### `__webpack_public_path__` (webpack-specific) - -Equals the config options `output.publicPath`. - - -### `__webpack_require__` (webpack-specific) - -The raw require function. This expression isn't parsed by the Parser for dependencies. - - -### `__webpack_chunk_load__` (webpack-specific) - -The internal chunk loading function. Takes two arguments: - -- `chunkId` The id for the chunk to load. -- `callback(require)` A callback function called once the chunk is loaded. - - -### `__webpack_modules__` (webpack-specific) - -Access to the internal object of all modules. - - -### `__webpack_hash__` (webpack-specific) - -This variable is only available with the `HotModuleReplacementPlugin` or the `ExtendedAPIPlugin`. It provides access to the hash of the compilation. - - -### `__non_webpack_require__` (webpack-specific) - -Generates a `require` function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available. - - -### `DEBUG` (webpack-specific) - -Equals the config option `debug`. - - -# Parser - -The `parser` instance, found in the `compiler`, is used to parse each module -being processed by webpack. The `parser` is yet another webpack class that -extends `tapable` and provides a variety of `tapable` hooks that can be used by -plugin authors to customize the parsing process. - -The `parser` is found within [module factories](/api/compiler-hooks/#normalmodulefactory) and therefore takes little -more work to access: - -``` js -compiler.hooks.normalModuleFactory.tap('MyPlugin', factory => { - factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => { - parser.hooks.someHook.tap(/* ... */); - }); -}); -``` - -As with the `compiler`, `tapAsync` and `tapPromise` may also be available -depending on the type of hook. - - -## Hooks - -The following lifecycle hooks are exposed by the `parser` and can be accessed -as such: - - -### evaluateTypeof - -`SyncBailHook` - -Evaluate the type of an identifier. - -Parameters: `expression` - - -### evaluate - -`SyncBailHook` - -Evaluate an expression. - -Parameters: `expression` - - -### evaluateIdentifier - -`SyncBailHook` - -Evaluate an identifier that is a free variable. - -Parameters: `expression` - - -### evaluateDefinedIdentifier - -`SyncBailHook` - -Evaluate an identifier that is a defined variable. - -Parameters: `expression` - - -### evaluateCallExpressionMember - -`SyncBailHook` - -Evaluate a call to a member function of a successfully evaluated expression. - -Parameters: `expression` `param` - - -### statement - -`SyncBailHook` - -General purpose hook that is called when parsing statements in a code fragment. - -Parameters: `statement` - - -### statementIf - -`SyncBailHook` - -... - -Parameters: `statement` - - -### label - -`SyncBailHook` - -... - -Parameters: `statement` - - -### import - -`SyncBailHook` - -... - -Parameters: `statement` `source` - - -### importSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `source` `exportName` `identifierName` - - -### export - -`SyncBailHook` - -... - -Parameters: `statement` - - -### exportImport - -`SyncBailHook` - -... - -Parameters: `statement` `source` - - -### exportDeclaration - -`SyncBailHook` - -... - -Parameters: `statement` `declaration` - - -### exportExpression - -`SyncBailHook` - -... - -Parameters: `statement` `declaration` - - -### exportSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `identifierName` `exportName` `index` - - -### exportImportSpecifier - -`SyncBailHook` - -... - -Parameters: `statement` `source` `identifierName` `exportName` `index` - - -### varDeclaration - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationLet - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationConst - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### varDeclarationVar - -`SyncBailHook` - -... - -Parameters: `declaration` - - -### canRename - -`SyncBailHook` - -... - -Parameters: `initExpression` - - -### rename - -`SyncBailHook` - -... - -Parameters: `initExpression` - - -### assigned - -`SyncBailHook` - -... - -Parameters: `expression` - - -### assign - -`SyncBailHook` - -... - -Parameters: `expression` - - -### typeof - -`SyncBailHook` - -... - -Parameters: `expression` - - -### call - -`SyncBailHook` - -... - -Parameters: `expression` - - -### callAnyMember - -`SyncBailHook` - -... - -Parameters: `expression` - - -### new - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expression - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expressionAnyMember - -`SyncBailHook` - -... - -Parameters: `expression` - - -### expressionConditionalOperator - -`SyncBailHook` - -... - -Parameters: `expression` - - -### program - -`SyncBailHook` - -Get access to the abstract syntax tree (AST) of a code fragment - -Parameters: `ast` `comments` diff --git a/src/content/concepts/_concepts_all.md b/src/content/concepts/_concepts_all.md deleted file mode 100644 index 7ea61cfe8aaa..000000000000 --- a/src/content/concepts/_concepts_all.md +++ /dev/null @@ -1,1086 +0,0 @@ - - -# Concepts - -At its core, __webpack__ is a _static module bundler_ for modern JavaScript applications. When webpack processes your application, it internally builds a [dependency graph](/concepts/dependency-graph/) which maps every module your project needs and generates one or more _bundles_. - -T> Learn more about JavaScript modules and webpack modules [here](/concepts/modules). - -Since version 4.0.0, __webpack does not require a configuration file__ to bundle your project, nevertheless it is [incredibly configurable](/configuration) to better fit your needs. - -To get started you only need to understand its __Core Concepts__: - -- [Entry](#entry) -- [Output](#output) -- [Loaders](#loaders) -- [Plugins](#plugins) -- [Mode](#mode) -- [Browser Compatibility](#browser-compatibility) - -This document is intended to give a __high-level__ overview of these concepts, while providing links to detailed concept specific use cases. - -For a better understanding of the ideas behind module bundlers and how they work under the hood consult these resources: - -- [Manually Bundling an Application](https://www.youtube.com/watch?v=UNMkLHzofQI) -- [Live Coding a Simple Module Bundler](https://www.youtube.com/watch?v=Gc9-7PBqOC8) -- [Detailed Explanation of a Simple Module Bundler](https://github.com/ronami/minipack) - - -## Entry - -An __entry point__ indicates which module webpack should use to begin building out its internal [dependency graph](/concepts/dependency-graph/). webpack will figure out which other modules and libraries that entry point depends on (directly and indirectly). - -By default its value is `./src/index.js`, but you can specify a different (or multiple entry points) by configuring the __entry__ property in the [webpack configuration](/configuration). For example: - -__webpack.config.js__ - -``` js -module.exports = { - entry: './path/to/my/entry/file.js' -}; -``` - -T> Learn more in the [entry points](/concepts/entry-points) section. - - -## Output - -The __output__ property tells webpack where to emit the _bundles_ it creates and how to name these files. It defaults to `./dist/main.js` for the main output file and to the `./dist` folder for any other generated file. - -You can configure this part of the process by specifying an `output` field in your configuration: - -__webpack.config.js__ - -```javascript -const path = require('path'); - -module.exports = { - entry: './path/to/my/entry/file.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'my-first-webpack.bundle.js' - } -}; -``` - -In the example above, we use the `output.filename` and the `output.path` properties to tell webpack the name of our bundle and where we want it to be emitted to. In case you're wondering about the path module being imported at the top, it is a core [Node.js module](https://nodejs.org/api/modules.html) that gets used to manipulate file paths. - -T> The `output` property has [many more configurable features](/configuration/output) and if you like to know more about the concepts behind it, you can [read more in the output section](/concepts/output). - - -## Loaders - -Out of the box, webpack only understands JavaScript and JSON files. __Loaders__ allow webpack to process other types of files and convert them into valid [modules](/concepts/modules) that can be consumed by your application and added to the dependency graph. - -W> Note that the ability to `import` any type of module, e.g. `.css` files, is a feature specific to webpack and may not be supported by other bundlers or task runners. We feel this extension of the language is warranted as it allows developers to build a more accurate dependency graph. - -At a high level, __loaders__ have two properties in your webpack configuration: - -1. The `test` property identifies which file or files should be transformed. -2. The `use` property indicates which loader should be used to do the transforming. - -__webpack.config.js__ - -```javascript -const path = require('path'); - -module.exports = { - output: { - filename: 'my-first-webpack.bundle.js' - }, - module: { - rules: [ - { test: /\.txt$/, use: 'raw-loader' } - ] - } -}; -``` - -The configuration above has defined a `rules` property for a single module with two required properties: `test` and `use`. This tells webpack's compiler the following: - -> "Hey webpack compiler, when you come across a path that resolves to a '.txt' file inside of a `require()`/`import` statement, __use__ the `raw-loader` to transform it before you add it to the bundle." - -W> It is important to remember that when defining rules in your webpack config, you are defining them under `module.rules` and not `rules`. For your benefit, webpack will warn you if this is done incorrectly. - -You can check further customization when including loaders in the [loaders section](/concepts/loaders). - - -## Plugins - -While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables. - -T> Check out the [plugin interface](/api/plugins) and how to use it to extend webpacks capabilities. - -In order to use a plugin, you need to `require()` it and add it to the `plugins` array. Most plugins are customizable through options. Since you can use a plugin multiple times in a config for different purposes, you need to create an instance of it by calling it with the `new` operator. - -__webpack.config.js__ - -```javascript -const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm -const webpack = require('webpack'); //to access built-in plugins - -module.exports = { - module: { - rules: [ - { test: /\.txt$/, use: 'raw-loader' } - ] - }, - plugins: [ - new HtmlWebpackPlugin({template: './src/index.html'}) - ] -}; -``` - -In the example above, the `html-webpack-plugin` generates an HTML file for your application by injecting automatically all your generated bundles. - -T> There are many plugins that webpack provides out of the box! Check out the [list of plugins](/plugins). - -Using plugins in your webpack config is straightforward - however, there are many use cases that are worth further exploration. [Learn more about them here](/concepts/plugins). - - -## Mode - -By setting the `mode` parameter to either `development`, `production` or `none`, you can enable webpack's built-in optimizations that correspond to each environment. The default value is `production`. - -```javascript -module.exports = { - mode: 'production' -}; -``` - -Learn more about the [mode configuration here](/concepts/mode) and what optimizations take place on each value. - - -## Browser Compatibility - -webpack supports all browsers that are [ES5-compliant](https://kangax.github.io/compat-table/es5/) (IE8 and below are not supported). webpack needs `Promise` for `import()` and `require.ensure()`. If you want to support older browsers, you will need to [load a polyfill](/guides/shimming/) before using these expressions. - - -# Entry Points - -As mentioned in [Getting Started](/guides/getting-started/#using-a-configuration), there are multiple ways to define the `entry` property in your webpack configuration. We will show you the ways you __can__ configure the `entry` property, in addition to explaining why it may be useful to you. - - -## Single Entry (Shorthand) Syntax - -Usage: `entry: string|Array<string>` - -__webpack.config.js__ - -```javascript -module.exports = { - entry: './path/to/my/entry/file.js' -}; -``` - -The single entry syntax for the `entry` property is a shorthand for: - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - main: './path/to/my/entry/file.js' - } -}; -``` - -T> __What happens when you pass an array to `entry`?__ Passing an array of file paths to the `entry` property creates what is known as a __"multi-main entry"__. This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk". - -This is a great choice when you are looking to quickly setup a webpack configuration for an application or tool with one entry point (i.e., a library). However, there is not much flexibility in extending or scaling your configuration with this syntax. - - -## Object Syntax - -Usage: `entry: {[entryChunkName: string]: string|Array<string>}` - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - app: './src/app.js', - adminApp: './src/adminApp.js' - } -}; -``` - -The object syntax is more verbose. However, this is the most scalable way of defining entry/entries in your application. - -T> __"Scalable webpack configurations"__ are ones that can be reused and combined with other partial configurations. This is a popular technique used to separate concerns by environment, build target and runtime. They are then merged using specialized tools like [webpack-merge](https://github.com/survivejs/webpack-merge). - - -## Scenarios - -Below is a list of entry configurations and their real-world use cases: - -### Separate App and Vendor Entries - -T> In webpack version < 4 it was common to add vendors as separate entrypoint to compile it as separate file (in combination with the `CommonsChunkPlugin`). This is discouraged in webpack 4. Instead the `optimization.splitChunks` option takes care of separating vendors and app modules and creating a separate file. __Do not__ create a entry for vendors or other stuff which is not the starting point of execution. - -### Multi Page Application - -__webpack.config.js__ - -```javascript -module.exports = { - entry: { - pageOne: './src/pageOne/index.js', - pageTwo: './src/pageTwo/index.js', - pageThree: './src/pageThree/index.js' - } -}; -``` - -__What does this do?__ We are telling webpack that we would like 3 separate dependency graphs (like the above example). - -__Why?__ In a multi-page application, the server is going to fetch a new HTML document for you. The page reloads this new document and assets are redownloaded. However, this gives us the unique opportunity to do multiple things: - -- Use `optimization.splitChunks` to create bundles of shared application code between each page. Multi-page applications that reuse a lot of code/modules between entry points can greatly benefit from these techniques, as the amount of entry points increase. - -T> As a rule of thumb: for each HTML document use exactly one entry point. - - -# Output - -Configuring the `output` configuration options tells webpack how to write the compiled files to disk. Note that, while there can be multiple `entry` points, only one `output` configuration is specified. - - -## Usage - -The minimum requirements for the `output` property in your webpack config is to set its value to an object including the following thing: - -- A `filename` to use for the output file(s). - -__webpack.config.js__ - -```javascript -module.exports = { - output: { - filename: 'bundle.js', - } -}; -``` - -This configuration would output a single `bundle.js` file into the `dist` directory. - - -## Multiple Entry Points - -If your configuration creates more than a single "chunk" (as with multiple entry points or when using plugins like CommonsChunkPlugin), you should use [substitutions](/configuration/output#output-filename) to ensure that each file has a unique name. - -```javascript -module.exports = { - entry: { - app: './src/app.js', - search: './src/search.js' - }, - output: { - filename: '[name].js', - path: __dirname + '/dist' - } -}; - -// writes to disk: ./dist/app.js, ./dist/search.js -``` - - -## Advanced - -Here's a more complicated example of using a CDN and hashes for assets: - -__config.js__ - -```javascript -module.exports = { - //... - output: { - path: '/home/proj/cdn/assets/[hash]', - publicPath: 'http://cdn.example.com/assets/[hash]/' - } -}; -``` - -In cases where the eventual `publicPath` of output files isn't known at compile time, it can be left blank and set dynamically at runtime via the `__webpack_public_path__` variable in the entry point file: - -```javascript -__webpack_public_path__ = myRuntimePublicPath; - -// rest of your application entry -``` - - -# Loaders - -Loaders are transformations that are applied on the source code of a module. They allow you to pre-process files as you `import` or “load” them. Thus, loaders are kind of like “tasks” in other build tools and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript or inline images as data URLs. Loaders even allow you to do things like `import` CSS files directly from your JavaScript modules! - - -## Example - -For example, you can use loaders to tell webpack to load a CSS file or to convert TypeScript to JavaScript. To do this, you would start by installing the loaders you need: - -``` bash -npm install --save-dev css-loader -npm install --save-dev ts-loader -``` - -And then instruct webpack to use the [`css-loader`](/loaders/css-loader) for every `.css` file and the [`ts-loader`](https://github.com/TypeStrong/ts-loader) for all `.ts` files: - -__webpack.config.js__ - -``` js -module.exports = { - module: { - rules: [ - { test: /\.css$/, use: 'css-loader' }, - { test: /\.ts$/, use: 'ts-loader' } - ] - } -}; -``` - - -## Using Loaders - -There are three ways to use loaders in your application: - -- [Configuration](#configuration) (recommended): Specify them in your __webpack.config.js__ file. -- [Inline](#inline): Specify them explicitly in each `import` statement. -- [CLI](#cli): Specify them within a shell command. - - -### Configuration - -[`module.rules`](/configuration/module/#module-rules) allows you to specify several loaders within your webpack configuration. -This is a concise way to display loaders, and helps to maintain clean code. It also offers you a full overview of each respective loader. - -Loaders are evaluated/executed from right to left. In the example below execution starts with sass-loader, continues with css-loader and finally ends with style-loader. See ["Loader Features"](/concepts/loaders/#loader-features) for more information about loaders order. - -```js-with-links-with-details -module.exports = { - module: { - rules: [ - { - test: /\.css$/, - use: [ - { loader: ['style-loader'](/loaders/style-loader) }, - { - loader: ['css-loader'](/loaders/css-loader), - options: { - modules: true - } - }, - { loader: ['sass-loader'](/loaders/sass-loader) } - ] - } - ] - } -}; -``` - - -### Inline - -It's possible to specify loaders in an `import` statement, or any [equivalent "importing" method](/api/module-methods). Separate loaders from the resource with `!`. Each part is resolved relative to the current directory. - -```js -import Styles from 'style-loader!css-loader?modules!./styles.css'; -``` - -It's possible to override any loaders in the configuration by prefixing the entire rule with `!`. - -Options can be passed with a query parameter, e.g. `?key=value&foo=bar`, or a JSON object, e.g. `?{"key":"value","foo":"bar"}`. - -T> Use `module.rules` whenever possible, as this will reduce boilerplate in your source code and allow you to debug or locate a loader faster if something goes south. - - -### CLI - -You can also use loaders through the CLI: - -```sh -webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader' -``` - -This uses the `jade-loader` for `.jade` files, and the [`style-loader`](/loaders/style-loader) and [`css-loader`](/loaders/css-loader) for `.css` files. - - -## Loader Features - -- Loaders can be chained. Each loader in the chain applies transformations to the processed resource. A chain is executed in reverse order. The first loader passes its result (resource with applied transformations) to the next one, and so forth. Finally, webpack expects JavaScript to be returned by the last loader in the chain. -- Loaders can be synchronous or asynchronous. -- Loaders run in Node.js and can do everything that’s possible there. -- Loaders can be configured with an `options` object (using `query` parameters to set options is still supported but has been deprecated). -- Normal modules can export a loader in addition to the normal `main` via `package.json` with the `loader` field. -- Plugins can give loaders more features. -- Loaders can emit additional arbitrary files. - -Loaders allow more power in the JavaScript ecosystem through preprocessing -functions (loaders). Users now have more flexibility to include fine-grained logic such as compression, packaging, language translations and [more](/loaders). - - -## Resolving Loaders - -Loaders follow the standard [module resolution](/concepts/module-resolution/). In most cases it will be loaded from the [module path](/concepts/module-resolution/#module-paths) (think `npm install`, `node_modules`). - -A loader module is expected to export a function and be written in Node.js compatible JavaScript. They are most commonly managed with npm, but you can also have custom loaders as files within your application. By convention, loaders are usually named `xxx-loader` (e.g. `json-loader`). See ["How to Write a Loader?"](/development/how-to-write-a-loader) for more information. - - -# Mode - -Providing the `mode` configuration option tells webpack to use its built-in optimizations accordingly. - -`string` - -T> Possible values for `mode` are: `none`, `development` or `production`(default). - -## Usage - -Just provide the `mode` option in the config: - -```javascript -module.exports = { - mode: 'production' -}; -``` - - -or pass it as a [CLI](/api/cli/) argument: - -```bash -webpack --mode=production -``` - -The following string values are supported: - -Option | Description ---------------------- | ----------------------- -`development` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `development`. Enables `NamedChunksPlugin` and `NamedModulesPlugin`. -`production` | Sets `process.env.NODE_ENV` on `DefinePlugin` to value `production`. Enables `FlagDependencyUsagePlugin`, `FlagIncludedChunksPlugin`, `ModuleConcatenationPlugin`, `NoEmitOnErrorsPlugin`, `OccurrenceOrderPlugin`, `SideEffectsFlagPlugin` and `TerserPlugin`. -`none` | Opts out of any default optimization options - -If not set, webpack sets `production` as the default value for `mode`. The supported values for mode are: - -T> Please remember that setting `NODE_ENV` doesn't automatically set `mode`. - - -### Mode: development - - -```diff -// webpack.development.config.js -module.exports = { -+ mode: 'development' -- devtool: 'eval', -- cache: true, -- performance: { -- hints: false -- }, -- output: { -- pathinfo: true -- }, -- optimization: { -- namedModules: true, -- namedChunks: true, -- nodeEnv: 'development', -- flagIncludedChunks: false, -- occurrenceOrder: false, -- sideEffects: false, -- usedExports: false, -- concatenateModules: false, -- splitChunks: { -- hidePathInfo: false, -- minSize: 10000, -- maxAsyncRequests: Infinity, -- maxInitialRequests: Infinity, -- }, -- noEmitOnErrors: false, -- checkWasmTypes: false, -- minimize: false, -- }, -- plugins: [ -- new webpack.NamedModulesPlugin(), -- new webpack.NamedChunksPlugin(), -- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), -- ] -} -``` - - -### Mode: production - - -```diff -// webpack.production.config.js -module.exports = { -+ mode: 'production', -- performance: { -- hints: 'warning' -- }, -- output: { -- pathinfo: false -- }, -- optimization: { -- namedModules: false, -- namedChunks: false, -- nodeEnv: 'production', -- flagIncludedChunks: true, -- occurrenceOrder: true, -- sideEffects: true, -- usedExports: true, -- concatenateModules: true, -- splitChunks: { -- hidePathInfo: true, -- minSize: 30000, -- maxAsyncRequests: 5, -- maxInitialRequests: 3, -- }, -- noEmitOnErrors: true, -- checkWasmTypes: true, -- minimize: true, -- }, -- plugins: [ -- new TerserPlugin(/* ... */), -- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), -- new webpack.optimize.ModuleConcatenationPlugin(), -- new webpack.NoEmitOnErrorsPlugin() -- ] -} -``` - - -### Mode: none - - -```diff -// webpack.custom.config.js -module.exports = { -+ mode: 'none', -- performance: { -- hints: false -- }, -- optimization: { -- flagIncludedChunks: false, -- occurrenceOrder: false, -- sideEffects: false, -- usedExports: false, -- concatenateModules: false, -- splitChunks: { -- hidePathInfo: false, -- minSize: 10000, -- maxAsyncRequests: Infinity, -- maxInitialRequests: Infinity, -- }, -- noEmitOnErrors: false, -- checkWasmTypes: false, -- minimize: false, -- }, -- plugins: [] -} -``` - -If you want to change the behavior according to the __mode__ variable inside the _webpack.config.js_, you have to export a function instead of an object: - -```javascript -var config = { - entry: './app.js' - //... -}; - -module.exports = (env, argv) => { - - if (argv.mode === 'development') { - config.devtool = 'source-map'; - } - - if (argv.mode === 'production') { - //... - } - - return config; -}; -``` - - -# Plugins - -__Plugins__ are the [backbone](https://github.com/webpack/tapable) of webpack. webpack itself is built on the __same plugin system__ that you use in your webpack configuration! - -They also serve the purpose of doing __anything else__ that a [loader](/concepts/loaders) cannot do. - - -## Anatomy - -A webpack __plugin__ is a JavaScript object that has an [`apply`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) method. This `apply` method is called by the webpack compiler, giving access to the __entire__ compilation lifecycle. - -__ConsoleLogOnBuildWebpackPlugin.js__ - -```javascript -const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; - -class ConsoleLogOnBuildWebpackPlugin { - apply(compiler) { - compiler.hooks.run.tap(pluginName, compilation => { - console.log('The webpack build process is starting!!!'); - }); - } -} -``` - -The first parameter of the tap method of the compiler hook should be a camelized version of the plugin name. It is advisable to use a constant for this so it can be reused in all hooks. - -## Usage - -Since __plugins__ can take arguments/options, you must pass a `new` instance to the `plugins` property in your webpack configuration. - -Depending on how you are using webpack, there are multiple ways to use plugins. - - -### Configuration - -__webpack.config.js__ - -```javascript -const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm -const webpack = require('webpack'); //to access built-in plugins -const path = require('path'); - -module.exports = { - entry: './path/to/my/entry/file.js', - output: { - filename: 'my-first-webpack.bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.(js|jsx)$/, - use: 'babel-loader' - } - ] - }, - plugins: [ - new webpack.ProgressPlugin(), - new HtmlWebpackPlugin({template: './src/index.html'}) - ] -}; -``` - - -### Node API - -When using the Node API, you can also pass plugins via the `plugins` property in the configuration. - -__some-node-script.js__ - -```javascript -const webpack = require('webpack'); //to access webpack runtime -const configuration = require('./webpack.config.js'); - -let compiler = webpack(configuration); - -new webpack.ProgressPlugin().apply(compiler); - -compiler.run(function(err, stats) { - // ... -}); -``` - -T> Did you know: The example seen above is extremely similar to the [webpack runtime itself!](https://github.com/webpack/webpack/blob/e7087ffeda7fa37dfe2ca70b5593c6e899629a2c/bin/webpack.js#L290-L292) There are lots of great usage examples hiding in the [webpack source code](https://github.com/webpack/webpack) that you can apply to your own configurations and scripts! - - -# Configuration - -You may have noticed that few webpack configurations look exactly alike. This is because __webpack's configuration file is a JavaScript file that exports a webpack [configuration](/configuration/).__ This configuration is then processed by webpack based upon its defined properties. - -Because it's a standard Node.js CommonJS module, you __can do the following__: - -- import other files via `require(...)` -- use utilities on npm via `require(...)` -- use JavaScript control flow expressions i. e. the `?:` operator -- use constants or variables for often used values -- write and execute functions to generate a part of the configuration - -Use these features when appropriate. - -While they are technically feasible, __the following practices should be avoided__: - -- Access CLI arguments, when using the webpack CLI (instead write your own CLI, or [use `--env`](/configuration/configuration-types/)) -- Export non-deterministic values (calling webpack twice should result in the same output files) -- Write long configurations (instead split the configuration into multiple files) - -T> The most important part to take away from this document is that there are many different ways to format and style your webpack configuration. The key is to stick with something consistent that you and your team can understand and maintain. - -The examples below describe how webpack's configuration can be both expressive and configurable because _it is code_: - -## Simple Configuration - -__webpack.config.js__ - -```javascript -var path = require('path'); - -module.exports = { - mode: 'development', - entry: './foo.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'foo.bundle.js' - } -}; -``` - -_See_: [Configuration section](/configuration/) for the all supported configuration options - -## Multiple Targets - -Along with exporting a single configuration as an object, [function](/configuration/configuration-types/#exporting-a-function) or [Promise](/configuration/configuration-types/#exporting-a-promise), you can export multiple configurations. - -_See_: [Exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) - -## Using other Configuration Languages - -webpack accepts configuration files written in multiple programming and data languages. - -_See_: [Configuration Languages](/configuration/configuration-languages/) - - -# Modules - -In [modular programming](https://en.wikipedia.org/wiki/Modular_programming), developers break programs up into discrete chunks of functionality called a _module_. - -Each module has a smaller surface area than a full program, making verification, debugging, and testing trivial. -Well-written _modules_ provide solid abstractions and encapsulation boundaries, so that each module has a coherent design and a clear purpose within the overall application. - -Node.js has supported modular programming almost since its inception. -On the web, however, support for _modules_ has been slow to arrive. -Multiple tools exist that support modular JavaScript on the web, with a variety of benefits and limitations. -webpack builds on lessons learned from these systems and applies the concept of _modules_ to any file in your project. - -## What is a webpack Module - -In contrast to [Node.js modules](https://nodejs.org/api/modules.html), webpack _modules_ can express their _dependencies_ in a variety of ways. A few examples are: - -- An [ES2015 `import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) statement -- A [CommonJS](http://www.commonjs.org/specs/modules/1.0/) `require()` statement -- An [AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md) `define` and `require` statement -- An [`@import` statement](https://developer.mozilla.org/en-US/docs/Web/CSS/@import) inside of a css/sass/less file. -- An image url in a stylesheet (`url(...)`) or html (`<img src=...>`) file. - -T> webpack 1 requires a specific loader to convert ES2015 `import`, however this is possible out of the box via webpack 2 - -## Supported Module Types - -webpack supports modules written in a variety of languages and preprocessors, via _loaders_. _Loaders_ describe to webpack __how__ to process non-JavaScript _modules_ and include these _dependencies_ into your _bundles_. -The webpack community has built _loaders_ for a wide variety of popular languages and language processors, including: - -- [CoffeeScript](http://coffeescript.org) -- [TypeScript](https://www.typescriptlang.org) -- [ESNext (Babel)](https://babeljs.io) -- [Sass](http://sass-lang.com) -- [Less](http://lesscss.org) -- [Stylus](http://stylus-lang.com) - -And many others! Overall, webpack provides a powerful and rich API for customization that allows one to use webpack for __any stack__, while staying __non-opinionated__ about your development, testing, and production workflows. - -For a full list, see [__the list of loaders__](/loaders) or [__write your own__](/api/loaders). - - -# Why webpack - -To understand why you should use webpack let's do a recap of how we used JavaScript on the web before bundlers were a thing. - -There are two ways to run JavaScript in a browser. First, include a script for each functionality you want to implement, the issue is that the solution is hard to scale as loading too many scripts causes a network bottleneck. The other alternative is to load a big .js file containing all your project code, but this results in an unmaintainable scripts that causes problems in scope, size, readability, fragility and monolith files. - - -## IIFE's - Immediately invoked function expressions - -IIFEs solve scoping issues for large projects. When script files are wrapped by an IIFE, you can safely concatenate or safely combine files without concern of scope collision. - -This lead to tools like Make, Gulp, Grunt, Broccoli or Brunch. These tools are known as task runners and they are used, among other purposes, to concatenate all your project files together in order to solve some of the issues mentioned before. - -However, anytime you want to change one file you have to rebuild the whole thing. Concatenating makes it trivial to reuse scripts across files and makes build optimizations more difficult to implement. How do you even know what code is being used and which is not? - -If you are only using one function from lodash or one date utility from moment.js you are actually adding the entire library and just squishing it together. How do you treeshake the dependencies on your code? Also, lazy loading chunks of code can be hard to achieve at scale and requires a lot of manual work from the developer. - - -## Birth of JavaScript Modules happened thanks to Node.js - -webpack runs on Node.js, a JavaScript runtime that can be used in computers and servers outside a browser environment. - -When Node.js was released a new era started, and it came with new challenges. Now that JavaScript is not running in a browser, how are Node applications supposed to load new chunks of code? There are no html files and script tags that can be added to it. - -CommonJS came out and introduced `require`, which allows you to load and use a module in the current file. This solves scope issues out of the box and which code is used becomes clear since we need to import each module that we are going to need. - - -## npm + Node.js + modules -- mass distribution - -JavaScript is taking over the world as a language, as a platform and as a way to rapidly develop and create fast running applications. - -But there is no browser support for CommonJS. There are no [live bindings](https://medium.com/webpack/the-state-of-javascript-modules-4636d1774358). There are problems with circular references. Sync module resolution loader is slow. While CommonJS was a great solution for Node.js projects, browsers didn't support modules. That's when bundlers and tools like Browserify, RequireJS and SystemJS were created to solve this limitation making it possible to write CommonJS modules that run in a browser. - - -## ESM - ECMAScript Modules - -The good news for web projects is that modules are becoming an official feature in ECMAScript standard, though browser support is still short and early implementations show that bundling is still faster and recommended today. - - -## Wouldn't it be nice… - -...to have something that will not only let us write modules but also support any module format (at least until we get to ESM) and that can handle resources and assets at the same time? - -This is why webpack exists. It's a tool that not only let's you bundle your JavaScript applications, supporting both ESM and CommonJS, but can be extended to support all different kinds of assets like images, fonts and stylesheets. - -webpack cares a lot about performance and it's always adding and improving features like async chunk loading and prefetching to help you deliver the best possible version of your project to the user, always caring about loading times and performance. - - -# Module Resolution - -A resolver is a library which helps in locating a module by its absolute path. -A module can be required as a dependency from another module as: - -```js -import foo from 'path/to/module'; -// or -require('path/to/module'); -``` - -The dependency module can be from the application code or a third party library. The resolver helps -webpack find the module code that needs to be included in the bundle for every such `require`/`import` statement. -webpack uses [enhanced-resolve](https://github.com/webpack/enhanced-resolve) to resolve file paths while bundling modules. - - -## Resolving rules in webpack - -Using `enhanced-resolve`, webpack can resolve three kinds of file paths: - - -### Absolute paths - -```js -import '/home/me/file'; - -import 'C:\\Users\\me\\file'; -``` - -Since we already have the absolute path to the file, no further resolution is required. - - -### Relative paths - -```js -import '../src/file1'; -import './file2'; -``` - -In this case, the directory of the resource file where the `import` or `require` occurs is taken to be the context directory. The relative path specified in the `import/require` is joined to this context path to produce the absolute path to the module. - - -### Module paths - -```js -import 'module'; -import 'module/lib/file'; -``` - -Modules are searched for inside all directories specified in [`resolve.modules`](/configuration/resolve/#resolve-modules). -You can replace the original module path by an alternate path by creating an alias for it using [`resolve.alias`](/configuration/resolve/#resolve-alias) configuration option. - -Once the path is resolved based on the above rule, the resolver checks to see if the path points to a file or a directory. If the path points to a file: - -- If the path has a file extension, then the file is bundled straightaway. -- Otherwise, the file extension is resolved using the [`resolve.extensions`](/configuration/resolve/#resolve-extensions) option, which tells the resolver which extensions (eg - `.js`, `.jsx`) are acceptable for resolution. - -If the path points to a folder, then the following steps are taken to find the right file with the right extension: - -- If the folder contains a `package.json` file, then fields specified in [`resolve.mainFields`](/configuration/resolve/#resolve-mainfields) configuration option are looked up in order, and the first such field in `package.json` determines the file path. -- If there is no `package.json` or if the main fields do not return a valid path, file names specified in the [`resolve.mainFiles`](/configuration/resolve/#resolve-mainfiles) configuration option are looked for in order, to see if a matching filename exists in the imported/required directory . -- The file extension is then resolved in a similar way using the `resolve.extensions` option. - -webpack provides reasonable [defaults](/configuration/resolve) for these options depending on your build target. - - -## Resolving Loaders - -This follows the same rules as those specified for file resolution. But the [`resolveLoader`](/configuration/resolve/#resolveloader) configuration option can be used to have separate resolution rules for loaders. - - -## Caching - -Every filesystem access is cached, so that multiple parallel or serial requests to the same file occur faster. In [watch mode](/configuration/watch/#watch), only modified files are evicted from the cache. If watch mode is off, then the cache gets purged before every compilation. - - -See [Resolve API](/configuration/resolve) to learn more on the configuration options mentioned above. - - -# Dependency Graph - -Any time one file depends on another, webpack treats this as a _dependency_. This allows webpack to take non-code assets, such as images or web fonts, and also provide them as _dependencies_ for your application. - -When webpack processes your application, it starts from a list of modules defined on the command line or in its config file. -Starting from these [_entry points_](/concepts/entry-points/), webpack recursively builds a _dependency graph_ that includes every module your application needs, then bundles all of those modules into a small number of _bundles_ - often, just one - to be loaded by the browser. - -T> Bundling your application is especially powerful for _HTTP/1.1_ clients, as it minimizes the number of times your app has to wait while the browser starts a new request. For _HTTP/2_, you can also use [Code Splitting](/guides/code-splitting/) to achieve best results. - - -# Targets - -Because JavaScript can be written for both server and browser, webpack offers multiple deployment _targets_ that you can set in your webpack [configuration](/configuration). - -W> The webpack `target` property is not to be confused with the `output.libraryTarget` property. For more information see [our guide](/concepts/output/) on the `output` property. - -## Usage - -To set the `target` property, you simply set the target value in your webpack config: - -__webpack.config.js__ - -```javascript -module.exports = { - target: 'node' -}; -``` - -In the example above, using `node` webpack will compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks and not touch any built in modules like `fs` or `path`). - -Each _target_ has a variety of deployment/environment specific additions, support to fit its needs. See what [targets are available](/configuration/target/). - -?>Further expansion for other popular target values - -## Multiple Targets - -Although webpack does __not__ support multiple strings being passed into the `target` property, you can create an isomorphic library by bundling two separate configurations: - -__webpack.config.js__ - -```javascript -const path = require('path'); -const serverConfig = { - target: 'node', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'lib.node.js' - } - //… -}; - -const clientConfig = { - target: 'web', // <=== can be omitted as default is 'web' - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'lib.js' - } - //… -}; - -module.exports = [ serverConfig, clientConfig ]; -``` - -The example above will create a `lib.js` and `lib.node.js` file in your `dist` folder. - -## Resources - -As seen from the options above there are multiple different deployment _targets_ that you can choose from. Below is a list of examples, and resources that you can refer to. - -- __[compare-webpack-target-bundles](https://github.com/TheLarkInn/compare-webpack-target-bundles)__: A great resource for testing and viewing different webpack _targets_. Also great for bug reporting. -- __[Boilerplate of Electron-React Application](https://github.com/chentsulin/electron-react-boilerplate)__: A good example of a build process for electron's main process and renderer process. - -?> Need to find up to date examples of these webpack targets being used in live code or boilerplates. - - -# The Manifest - -In a typical application or site built with webpack, there are three main types of code: - -1. The source code you, and maybe your team, have written. -2. Any third-party library or "vendor" code your source is dependent on. -3. A webpack runtime and __manifest__ that conducts the interaction of all modules. - -This article will focus on the last of these three parts, the runtime and in particular the manifest. - - -## Runtime - -The runtime, along with the manifest data, is basically all the code webpack needs to connect your modularized application while it's running in the browser. It contains the loading and resolving logic needed to connect your modules as they interact. This includes connecting modules that have already been loaded into the browser as well as logic to lazy-load the ones that haven't. - - -## Manifest - -Once your application hits the browser in the form of `index.html` file, some bundles and a variety of other assets required by your application must be loaded and linked somehow. That `/src` directory you meticulously laid out is now bundled, minified and maybe even split into smaller chunks for lazy-loading by webpack's [`optimization`](/configuration/optimization/). So how does webpack manage the interaction between all of your required modules? This is where the manifest data comes in... - -As the compiler enters, resolves, and maps out your application, it keeps detailed notes on all your modules. This collection of data is called the "Manifest" and it's what the runtime will use to resolve and load modules once they've been bundled and shipped to the browser. No matter which [module syntax](/api/module-methods) you have chosen, those `import` or `require` statements have now become `__webpack_require__` methods that point to module identifiers. Using the data in the manifest, the runtime will be able to find out where to retrieve the modules behind the identifiers. - - -## The Problem - -So now you have a little bit of insight about how webpack works behind the scenes. "But, how does this affect me?", you might ask. The simple answer is that most of the time it doesn't. The runtime will do its thing, utilizing the manifest, and everything will appear to just magically work once your application hits the browser. However, if you decide to improve your projects performance by utilizing browser caching, this process will all of a sudden become an important thing to understand. - -By using content hashes within your bundle file names, you can indicate to the browser when the contents of a file has changed thus invalidating the cache. Once you start doing this though, you'll immediately notice some funny behavior. Certain hashes change even when their contents apparently do not. This is caused by the injection of the runtime and manifest which changes every build. - -See [the manifest section](/guides/output-management/#the-manifest) of our _Output management_ guide to learn how to extract the manifest, and read the guides below to learn more about the intricacies of long term caching. - - -# Hot Module Replacement - -Hot Module Replacement (HMR) exchanges, adds, or removes [modules](/concepts/modules/) while an application is running, without a full reload. This can significantly speed up development in a few ways: - -- Retain application state which is lost during a full reload. -- Save valuable development time by only updating what's changed. -- Modifications made to CSS/JS in the source code results in an instant browser update which is almost comparable to changing styles directly in the browser's dev tools. - - -## How It Works - -Let's go through some different viewpoints to understand exactly how HMR works... - -### In the Application - -The following steps allow modules to be swapped in and out of an application: - -1. The application asks the HMR runtime to check for updates. -2. The runtime asynchronously downloads the updates and notifies the application. -3. The application then asks the runtime to apply the updates. -4. The runtime synchronously applies the updates. - -You can set up HMR so that this process happens automatically, or you can choose to require user interaction for updates to occur. - - -### In the Compiler - -In addition to normal assets, the compiler needs to emit an "update" to allow updating from previous version to the new version. The "update" consists of two parts: - -1. The updated [manifest](/concepts/manifest) (JSON) -2. One or more updated chunks (JavaScript) - -The manifest contains the new compilation hash and a list of all updated chunks. Each of these chunks contains the new code for all updated modules (or a flag indicating that the module was removed). - -The compiler ensures that module IDs and chunk IDs are consistent between these builds. It typically stores these IDs in memory (e.g. with [webpack-dev-server](/configuration/dev-server/)), but it's also possible to store them in a JSON file. - - -### In a Module - -HMR is an opt-in feature that only affects modules containing HMR code. One example would be patching styling through the [`style-loader`](https://github.com/webpack-contrib/style-loader). In order for patching to work, the `style-loader` implements the HMR interface; when it receives an update through HMR, it replaces the old styles with the new ones. - -Similarly, when implementing the HMR interface in a module, you can describe what should happen when the module is updated. However, in most cases, it's not mandatory to write HMR code in every module. If a module has no HMR handlers, the update bubbles up. This means that a single handler can update a complete module tree. If a single module from the tree is updated, the entire set of dependencies is reloaded. - -See the [HMR API page](/api/hot-module-replacement) for details on the `module.hot` interface. - - -### In the Runtime - -Here things get a bit more technical... if you're not interested in the internals, feel free to jump to the [HMR API page](/api/hot-module-replacement) or [HMR guide](/guides/hot-module-replacement). - -For the module system runtime, additional code is emitted to track module `parents` and `children`. On the management side, the runtime supports two methods: `check` and `apply`. - -A `check` makes an HTTP request to the update manifest. If this request fails, there is no update available. If it succeeds, the list of updated chunks is compared to the list of currently loaded chunks. For each loaded chunk, the corresponding update chunk is downloaded. All module updates are stored in the runtime. When all update chunks have been downloaded and are ready to be applied, the runtime switches into the `ready` state. - -The `apply` method flags all updated modules as invalid. For each invalid module, there needs to be an update handler in the module or in its parent(s). Otherwise, the invalid flag bubbles up and invalidates parent(s) as well. Each bubble continues until the app's entry point or a module with an update handler is reached (whichever comes first). If it bubbles up from an entry point, the process fails. - -Afterwards, all invalid modules are disposed (via the dispose handler) and unloaded. The current hash is then updated and all `accept` handlers are called. The runtime switches back to the `idle` state and everything continues as normal. - - -## Get Started - -HMR can be used in development as a LiveReload replacement. [webpack-dev-server](/configuration/dev-server/) supports a `hot` mode in which it tries to update with HMR before trying to reload the whole page. See the [Hot Module Replacement guide](/guides/hot-module-replacement) for details. - -T> As with many other features, webpack's power lies in its customizability. There are _many_ ways of configuring HMR depending on the needs of a particular project. However, for most purposes, `webpack-dev-server` is a good fit and will allow you to get started with HMR quickly. diff --git a/src/content/configuration/_configuration_all.md b/src/content/configuration/_configuration_all.md deleted file mode 100644 index a1e52dc062a1..000000000000 --- a/src/content/configuration/_configuration_all.md +++ /dev/null @@ -1,5315 +0,0 @@ - - -# Configuration - -Out of the box, webpack won't require you to use a configuration file. However, it will assume the entry point of your project is `src/index` and will output the result in `dist/main.js` minified and optimized for production. - -Usually your projects will need to extend this functionality, for this you can create a `webpack.config.js` file in the root folder and webpack will automatically use it. - -All the available configuration options are specified below. - -T> New to webpack? Check out our guide to some of webpack's [core concepts](/concepts/) to get started! - -## Options - -Click on the name of each option in the configuration code below to jump to the detailed documentation. Also note that the items with arrows can be expanded to show more examples and, in some cases, more advanced configuration. - -W> Notice that throughout the configuration we use Node's built-in [path module](https://nodejs.org/api/path.html) and prefix it with the [__dirname](https://nodejs.org/docs/latest/api/globals.html#globals_dirname) global. This prevents file path issues between operating systems and allows relative paths to work as expected. See [this section](https://nodejs.org/api/path.html#path_windows_vs_posix) for more info on POSIX vs. Windows paths. - -__webpack.config.js__ - -```js-with-links-with-details -const path = require('path'); - -module.exports = { - <details><summary>[mode](/concepts/mode): "production", // "production" | "development" | "none"</summary> - [mode](/concepts/mode): "production", // enable many optimizations for production builds - [mode](/concepts/mode): "development", // enabled useful tools for development - [mode](/concepts/mode): "none", // no defaults - </details> - // Chosen mode tells webpack to use its built-in optimizations accordingly. - <details><summary>[entry](/configuration/entry-context#entry): "./app/entry", // string | object | array</summary> - [entry](/configuration/entry-context#entry): ["./app/entry1", "./app/entry2"], - [entry](/configuration/entry-context#entry): { - a: "./app/entry-a", - b: ["./app/entry-b1", "./app/entry-b2"] - }, - </details> - // defaults to './src' - // Here the application starts executing - // and webpack starts bundling - [output](/configuration/output): { - // options related to how webpack emits results - [path](/configuration/output#output-path): path.resolve(__dirname, "dist"), // string - // the target directory for all output files - // must be an absolute path (use the Node.js path module) - <details><summary>[filename](/configuration/output#output-filename): "bundle.js", // string</summary> - [filename](/configuration/output#output-filename): "[name].js", // for multiple entry points - [filename](/configuration/output#output-filename): "[chunkhash].js", // for [long term caching](/guides/caching) - </details> - // the filename template for entry chunks - <details><summary>[publicPath](/configuration/output#output-publicpath): "/assets/", // string</summary> - [publicPath](/configuration/output#output-publicpath): "", - [publicPath](/configuration/output#output-publicpath): "https://cdn.example.com/", - </details> - // the url to the output directory resolved relative to the HTML page - [library](/configuration/output#output-library): "MyLibrary", // string, - // the name of the exported library - <details><summary>[libraryTarget](/configuration/output#output-librarytarget): "umd", // universal module definition</summary> - [libraryTarget](/configuration/output#output-librarytarget): "umd2", // universal module definition - [libraryTarget](/configuration/output#output-librarytarget): "commonjs2", // exported with module.exports - [libraryTarget](/configuration/output#output-librarytarget): "commonjs", // exported as properties to exports - [libraryTarget](/configuration/output#output-librarytarget): "amd", // defined with AMD defined method - [libraryTarget](/configuration/output#output-librarytarget): "this", // property set on this - [libraryTarget](/configuration/output#output-librarytarget): "var", // variable defined in root scope - [libraryTarget](/configuration/output#output-librarytarget): "assign", // blind assignment - [libraryTarget](/configuration/output#output-librarytarget): "window", // property set to window object - [libraryTarget](/configuration/output#output-librarytarget): "global", // property set to global object - [libraryTarget](/configuration/output#output-librarytarget): "jsonp", // jsonp wrapper - </details> - // the type of the exported library - <details><summary>/* Advanced output configuration (click to show) */</summary> - [pathinfo](/configuration/output#output-pathinfo): true, // boolean - // include useful path info about modules, exports, requests, etc. into the generated cod - [chunkFilename](/configuration/output#output-chunkfilename): "[id].js", - [chunkFilename](/configuration/output#output-chunkfilename): "[chunkhash].js", // for [long term caching](/guides/caching) - // the filename template for additional chunks - [jsonpFunction](/configuration/output#output-jsonpfunction): "myWebpackJsonp", // string - // name of the JSONP function used to load chunks - [sourceMapFilename](/configuration/output#output-sourcemapfilename): "[file].map", // string - [sourceMapFilename](/configuration/output#output-sourcemapfilename): "sourcemaps/[file].map", // string - // the filename template of the source map location - [devtoolModuleFilenameTemplate](/configuration/output#output-devtoolmodulefilenametemplate): "webpack:///[resource-path]", // string - // the name template for modules in a devtool - [devtoolFallbackModuleFilenameTemplate](/configuration/output#output-devtoolfallbackmodulefilenametemplate): "webpack:///[resource-path]?[hash]", // string - // the name template for modules in a devtool (used for conflicts) - [umdNamedDefine](/configuration/output#output-umdnameddefine): true, // boolean - // use a named AMD module in UMD library - [crossOriginLoading](/configuration/output#output-crossoriginloading): "use-credentials", // enum - [crossOriginLoading](/configuration/output#output-crossoriginloading): "anonymous", - [crossOriginLoading](/configuration/output#output-crossoriginloading): false, - // specifies how cross origin request are issued by the runtime - <details><summary>/* Expert output configuration (on own risk) */</summary> - [devtoolLineToLine](/configuration/output#output-devtoollinetoline): { - test: /\.jsx$/ - }, - // use a simple 1:1 mapped SourceMaps for these modules (faster) - [hotUpdateMainFilename](/configuration/output#output-hotupdatemainfilename): "[hash].hot-update.json", // string - // filename template for HMR manifest - [hotUpdateChunkFilename](/configuration/output#output-hotupdatechunkfilename): "[id].[hash].hot-update.js", // string - // filename template for HMR chunks - [sourcePrefix](/configuration/output#output-sourceprefix): "\t", // string - // prefix module sources in bundle for better readablitity - </details> - </details> - }, - [module](/configuration/module): { - // configuration regarding modules - [rules](/configuration/module#module-rules): [ - // rules for modules (configure loaders, parser options, etc.) - { - [test](/configuration/module#rule-test): /\.jsx?$/, - [include](/configuration/module#rule-include): [ - path.resolve(__dirname, "app") - ], - [exclude](/configuration/module#rule-exclude): [ - path.resolve(__dirname, "app/demo-files") - ], - // these are matching conditions, each accepting a regular expression or string - // test and include have the same behavior, both must be matched - // exclude must not be matched (takes preference over test and include) - // Best practices: - // - Use RegExp only in test and for filename matching - // - Use arrays of absolute paths in include and exclude - // - Try to avoid exclude and prefer include - [issuer](/configuration/module#rule-issuer): { test, include, exclude }, - // conditions for the issuer (the origin of the import) - [enforce](/configuration/module#rule-enforce): "pre", - [enforce](/configuration/module#rule-enforce): "post", - // flags to apply these rules, even if they are overridden (advanced option) - [loader](/configuration/module#rule-loader): "babel-loader", - // the loader which should be applied, it'll be resolved relative to the context - // -loader suffix is no longer optional in webpack2 for clarity reasons - // see [webpack 1 upgrade guide](/migrate/3/#automatic-loader-module-name-extension-removed) - [options](/configuration/module#rule-options-rule-query): { - presets: ["es2015"] - }, - // options for the loader - }, - { - [test](/configuration/module#rule-test): /\.html$/, - [use](/configuration/module#rule-use): [ - // apply multiple loaders and options - "htmllint-loader", - { - loader: "html-loader", - options: { - /* ... */ - } - } - ] - }, - { [oneOf](/configuration/module#rule-oneof): [ /* rules */ ] }, - // only use one of these nested rules - { [rules](/configuration/module#rule-rules): [ /* rules */ ] }, - // use all of these nested rules (combine with conditions to be useful) - { [resource](/configuration/module#rule-resource): { [and](/configuration/module#condition): [ /* conditions */ ] } }, - // matches only if all conditions are matched - { [resource](/configuration/module#rule-resource): { [or](/configuration/module#condition): [ /* conditions */ ] } }, - { [resource](/configuration/module#rule-resource): [ /* conditions */ ] }, - // matches if any condition is matched (default for arrays) - { [resource](/configuration/module#rule-resource): { [not](/configuration/module#condition): /* condition */ } } - // matches if the condition is not matched - ], - <details><summary>/* Advanced module configuration (click to show) */</summary> - [noParse](/configuration/module#module-noparse): [ - /special-library\.js$/ - ], - // do not parse this module - unknownContextRequest: ".", - unknownContextRecursive: true, - unknownContextRegExp: /^\.\/.*$/, - unknownContextCritical: true, - exprContextRequest: ".", - exprContextRegExp: /^\.\/.*$/, - exprContextRecursive: true, - exprContextCritical: true, - wrappedContextRegExp: /.*/, - wrappedContextRecursive: true, - wrappedContextCritical: false, - // specifies default behavior for dynamic requests - </details> - }, - [resolve](/configuration/resolve): { - // options for resolving module requests - // (does not apply to resolving to loaders) - [modules](/configuration/resolve#resolve-modules): [ - "node_modules", - path.resolve(__dirname, "app") - ], - // directories where to look for modules - [extensions](/configuration/resolve#resolve-extensions): [".js", ".json", ".jsx", ".css"], - // extensions that are used - [alias](/configuration/resolve#resolve-alias): { - // a list of module name aliases - "module": "new-module", - // alias "module" -> "new-module" and "module/path/file" -> "new-module/path/file" - "only-module$": "new-module", - // alias "only-module" -> "new-module", but not "only-module/path/file" -> "new-module/path/file" - "module": path.resolve(__dirname, "app/third/module.js"), - // alias "module" -> "./app/third/module.js" and "module/file" results in error - // modules aliases are imported relative to the current context - }, - <details><summary>/* alternative alias syntax (click to show) */</summary> - [alias](/configuration/resolve#resolve-alias): [ - { - name: "module", - // the old request - alias: "new-module", - // the new request - onlyModule: true - // if true only "module" is aliased - // if false "module/inner/path" is also aliased - } - ], - </details> - <details><summary>/* Advanced resolve configuration (click to show) */</summary> - [symlinks](/configuration/resolve#resolve-symlinks): true, - // follow symlinks to new location - [descriptionFiles](/configuration/resolve#resolve-descriptionfiles): ["package.json"], - // files that are read for package description - [mainFields](/configuration/resolve#resolve-mainfields): ["main"], - // properties that are read from description file - // when a folder is requested - [aliasFields](/configuration/resolve#resolve-aliasfields): ["browser"], - // properties that are read from description file - // to alias requests in this package - [enforceExtension](/configuration/resolve#resolve-enforceextension): false, - // if true request must not include an extensions - // if false request may already include an extension - [moduleExtensions](/configuration/resolve#resolveloader-moduleextensions): ["-module"], - [enforceModuleExtension](/configuration/resolve#resolve-enforcemoduleextension): false, - // like extensions/enforceExtension but for module names instead of files - [unsafeCache](/configuration/resolve#resolve-unsafecache): true, - [unsafeCache](/configuration/resolve#resolve-unsafecache): {}, - // enables caching for resolved requests - // this is unsafe as folder structure may change - // but performance improvement is really big - [cachePredicate](/configuration/resolve#resolve-cachepredicate): (path, request) => true, - // predicate function which selects requests for caching - [plugins](/configuration/resolve#resolve-plugins): [ - // ... - ] - // additional plugins applied to the resolver - </details> - }, - [performance](/configuration/performance): { - <details><summary>[hints](/configuration/performance#performance-hints): "warning", // enum </summary> - [hints](/configuration/performance#performance-hints): "error", // emit errors for perf hints - [hints](/configuration/performance#performance-hints): false, // turn off perf hints - </details> - [maxAssetSize](/configuration/performance#performance-maxassetsize): 200000, // int (in bytes), - [maxEntrypointSize](/configuration/performance#performance-maxentrypointsize): 400000, // int (in bytes) - [assetFilter](/configuration/performance#performance-assetfilter): function(assetFilename) { - // Function predicate that provides asset filenames - return assetFilename.endsWith('.css') || assetFilename.endsWith('.js'); - } - }, - <details><summary>[devtool](/configuration/devtool): "source-map", // enum </summary> - [devtool](/configuration/devtool): "inline-source-map", // inlines SourceMap into original file - [devtool](/configuration/devtool): "eval-source-map", // inlines SourceMap per module - [devtool](/configuration/devtool): "hidden-source-map", // SourceMap without reference in original file - [devtool](/configuration/devtool): "cheap-source-map", // cheap-variant of SourceMap without module mappings - [devtool](/configuration/devtool): "cheap-module-source-map", // cheap-variant of SourceMap with module mappings - [devtool](/configuration/devtool): "eval", // no SourceMap, but named modules. Fastest at the expense of detail. - </details> - // enhance debugging by adding meta info for the browser devtools - // source-map most detailed at the expense of build speed. - [context](/configuration/entry-context#context): __dirname, // string (absolute path!) - // the home directory for webpack - // the [entry](/configuration/entry-context) and [module.rules.loader](/configuration/module#rule-loader) option - // is resolved relative to this directory - <details><summary>[target](/configuration/target): "web", // enum</summary> - [target](/configuration/target): "webworker", // WebWorker - [target](/configuration/target): "node", // Node.js via require - [target](/configuration/target): "async-node", // Node.js via fs and vm - [target](/configuration/target): "node-webkit", // nw.js - [target](/configuration/target): "electron-main", // electron, main process - [target](/configuration/target): "electron-renderer", // electron, renderer process - [target](/configuration/target): (compiler) => { /* ... */ }, // custom - </details> - // the environment in which the bundle should run - // changes chunk loading behavior and available modules - <details><summary>[externals](/configuration/externals): ["react", /^@angular\//],</summary> - [externals](/configuration/externals): "react", // string (exact match) - [externals](/configuration/externals): /^[a-z\-]+($|\/)/, // Regex - [externals](/configuration/externals): { // object - angular: "this angular", // this["angular"] - react: { // UMD - commonjs: "react", - commonjs2: "react", - amd: "react", - root: "React" - } - }, - [externals](/configuration/externals): (request) => { /* ... */ return "commonjs " + request } - </details> - // Don't follow/bundle these modules, but request them at runtime from the environment - [serve](https://github.com/webpack-contrib/webpack-serve#options): { //object - port: 1337, - content: './dist', - // ... - }, - // lets you provide options for webpack-serve - <details><summary>[stats](/configuration/stats): "errors-only",</summary> - [stats](/configuration/stats): { //object - assets: true, - colors: true, - errors: true, - errorDetails: true, - hash: true, - // ... - }, - </details> - // lets you precisely control what bundle information gets displayed - [devServer](/configuration/dev-server): { - proxy: { // proxy URLs to backend development server - '/api': 'http://localhost:3000' - }, - contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location - compress: true, // enable gzip compression - historyApiFallback: true, // true for index.html upon 404, object for multiple paths - hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin - https: false, // true for self-signed, object for cert authority - noInfo: true, // only errors & warns on hot reload - // ... - }, - [plugins](plugins): [ - // ... - ], - // list of additional plugins - <details><summary>/* Advanced configuration (click to show) */</summary> - [resolveLoader](/configuration/resolve#resolveloader): { /* same as resolve */ } - // separate resolve options for loaders - [parallelism](other-options#parallelism): 1, // number - // limit the number of parallel processed modules - [profile](other-options#profile): true, // boolean - // capture timing information - [bail](other-options#bail): true, //boolean - // fail out on the first error instead of tolerating it. - [cache](other-options#cache): false, // boolean - // disable/enable caching - [watch](watch#watch): true, // boolean - // enables watching - [watchOptions](watch#watchoptions): { - [aggregateTimeout](watch#watchoptions-aggregatetimeout): 1000, // in ms - // aggregates multiple changes to a single rebuild - [poll](watch#watchoptions-poll): true, - [poll](watch#watchoptions-poll): 500, // interval in ms - // enables polling mode for watching - // must be used on filesystems that doesn't notify on change - // i. e. nfs shares - }, - [node](node): { - // Polyfills and mocks to run Node.js- - // environment code in non-Node environments. - [console](node#node-console): false, // boolean | "mock" - [global](node#node-global): true, // boolean | "mock" - [process](node#node-process): true, // boolean - [__filename](node#node-__filename): "mock", // boolean | "mock" - [__dirname](node#node-__dirname): "mock", // boolean | "mock" - [Buffer](node#node-buffer): true, // boolean | "mock" - [setImmediate](node#node-setimmediate): true // boolean | "mock" | "empty" - }, - [recordsPath](other-options#recordspath): path.resolve(__dirname, "build/records.json"), - [recordsInputPath](other-options#recordsinputpath): path.resolve(__dirname, "build/records.json"), - [recordsOutputPath](other-options#recordsoutputpath): path.resolve(__dirname, "build/records.json"), - // TODO - </details> -} -``` - -## Use custom configuration file - -If for some reason you want to use custom configuration file depending on certain situations you can change this via command line by using the `--config` flag. - -__package.json__ - -```json -"scripts": { - "build": "webpack --config prod.config.js" -} -``` - -## Configuration file generators - -Want to rapidly generate webpack configuration file for your project requirements with few clicks away? - -[Generate Custom Webpack Configuration](https://generatewebpackconfig.netlify.com/) is an interactive portal you can play around by selecting custom webpack configuration options tailored for your frontend project. It automatically generates a minimal webpack configuration based on your selection of loaders/plugins, etc. - -[Visual tool for creating webpack configs](https://webpack.jakoblind.no/) is an online configuration tool for creating webpack configuration file where you can select any combination of features you need. It also generates a full example project based on your webpack configs. - - -# Configuration Languages - -webpack accepts configuration files written in multiple programming and data languages. The list of supported file extensions can be found at the [node-interpret](https://github.com/js-cli/js-interpret) package. Using [node-interpret](https://github.com/js-cli/js-interpret), webpack can handle many different types of configuration files. - - -## TypeScript - -To write the webpack configuration in [TypeScript](http://www.typescriptlang.org/), you would first install the necessary dependencies, i.e., TypeScript and the relevant type definitions from the [DefinitelyTyped](https://definitelytyped.org/) project: - -``` bash -npm install --save-dev typescript ts-node @types/node @types/webpack -# and, if using webpack-dev-server -npm install --save-dev @types/webpack-dev-server -``` - -and then proceed to write your configuration: - -__webpack.config.ts__ - -```typescript -import path from 'path'; -import webpack from 'webpack'; - -const config: webpack.Configuration = { - mode: 'production', - entry: './foo.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'foo.bundle.js' - } -}; - -export default config; -``` - -Above sample assumes version >= 2.7 or newer of TypeScript is used with the new `esModuleInterop` and `allowSyntheticDefaultImports` compiler options in your `tsconfig.json` file. - -Note that you'll also need to check your `tsconfig.json` file. If the module in `compilerOptions` in `tsconfig.json` is `commonjs`, the setting is complete, else webpack will fail with an error. This occurs because `ts-node` does not support any module syntax other than `commonjs`. - -There are two solutions to this issue: - -- Modify `tsconfig.json`. -- Install `tsconfig-paths`. - -The __first option__ is to open your `tsconfig.json` file and look for `compilerOptions`. Set `target` to `"ES5"` and `module` to `"CommonJS"` (or completely remove the `module` option). - -The __second option__ is to install the `tsconfig-paths` package: - -``` bash -npm install --save-dev tsconfig-paths -``` - -And create a separate TypeScript configuration specifically for your webpack configs: - -__tsconfig-for-webpack-config.json__ - -``` json -{ - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "esModuleInterop": true - } -} -``` - -T> `ts-node` can resolve a `tsconfig.json` file using the environment variable provided by `tsconfig-path`. - -Then set the environment variable `process.env.TS_NODE_PROJECT` provided by `tsconfig-path` like so: - -__package.json__ - -```json -{ - "scripts": { - "build": "TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\" webpack" - } -} -``` - - -## CoffeeScript - -Similarly, to use [CoffeeScript](http://coffeescript.org/), you would first install the necessary dependencies: - -``` bash -npm install --save-dev coffee-script -``` - -and then proceed to write your configuration: - -__webpack.config.coffee__ - -<!-- eslint-skip --> - -```js -HtmlWebpackPlugin = require('html-webpack-plugin') -webpack = require('webpack') -path = require('path') - -config = - mode: 'production' - entry: './path/to/my/entry/file.js' - output: - path: path.resolve(__dirname, 'dist') - filename: 'my-first-webpack.bundle.js' - module: rules: [ { - test: /\.(js|jsx)$/ - use: 'babel-loader' - } ] - plugins: [ - new HtmlWebpackPlugin(template: './src/index.html') - ] - -module.exports = config -``` - - -## Babel and JSX - -In the example below JSX (React JavaScript Markup) and Babel are used to create a JSON Configuration that webpack can understand. - -> Courtesy of [Jason Miller](https://twitter.com/_developit/status/769583291666169862) - -First install the necessary dependencies: - -``` bash -npm install --save-dev babel-register jsxobj babel-preset-es2015 -``` - -__.babelrc__ - -``` json -{ - "presets": [ "es2015" ] -} -``` - -__webpack.config.babel.js__ - -``` js -import jsxobj from 'jsxobj'; - -// example of an imported plugin -const CustomPlugin = config => ({ - ...config, - name: 'custom-plugin' -}); - -export default ( - <webpack target="web" watch mode="production"> - <entry path="src/index.js" /> - <resolve> - <alias {...{ - react: 'preact-compat', - 'react-dom': 'preact-compat' - }} /> - </resolve> - <plugins> - <CustomPlugin foo="bar" /> - </plugins> - </webpack> -); -``` - -W> If you are using Babel elsewhere and have `modules` set to `false`, you will have to either maintain two separate `.babelrc` files or use `const jsxobj = require('jsxobj');` and `module.exports` instead of the new `import` and `export` syntax. This is because while Node does support many new ES6 features, they don't yet support ES6 module syntax. - - -# Configuration Types - -Besides exporting a single config object, there are a few more ways that cover other needs as well. - - -## Exporting a Function - -Eventually you will find the need to disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production). You have (at least) two options: - -One option is to export a function from your webpack config instead of exporting an object. The function will be invoked with two arguments: - -- An environment as the first parameter. See the [environment options CLI documentation](/api/cli#environment-options) for syntax examples. -- An options map (`argv`) as the second parameter. This describes the options passed to webpack, with keys such as [`output-filename`](/api/cli/#output-options) and [`optimize-minimize`](/api/cli/#optimize-options). - -```diff --module.exports = { -+module.exports = function(env, argv) { -+ return { -+ mode: env.production ? 'production' : 'development', -+ devtool: env.production ? 'source-maps' : 'eval', - plugins: [ - new TerserPlugin({ - terserOptions: { -+ compress: argv['optimize-minimize'] // only if -p or --optimize-minimize were passed - } - }) - ] -+ }; -}; -``` - - -## Exporting a Promise - -webpack will run the function exported by the configuration file and wait for a Promise to be returned. Handy when you need to asynchronously load configuration variables. - -```js -module.exports = () => { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve({ - entry: './app.js', - /* ... */ - }); - }, 5000); - }); -}; -``` - - -## Exporting multiple configurations - -Instead of exporting a single configuration object/function, you may export multiple configurations (multiple functions are supported since webpack 3.1.0). When running webpack, all configurations are built. For instance, this is useful for [bundling a library](/guides/author-libraries) for multiple [targets](/configuration/output#output-librarytarget) such as AMD and CommonJS: - -```js -module.exports = [{ - output: { - filename: './dist-amd.js', - libraryTarget: 'amd' - }, - name: 'amd', - entry: './app.js', - mode: 'production', -}, { - output: { - filename: './dist-commonjs.js', - libraryTarget: 'commonjs' - }, - name: 'commonjs', - entry: './app.js', - mode: 'production', -}]; -``` - -T> If you pass a name to [`--config-name`](/api/cli/#config-options) flag, webpack will only build that specific configuration. - - -# Entry and Context - -The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. - - -## `context` - -`string` - -The base directory, an __absolute path__, for resolving entry points and loaders from configuration. - -``` js -module.exports = { - //... - context: path.resolve(__dirname, 'app') -}; -``` - -By default the current directory is used, but it's recommended to pass a value in your configuration. This makes your configuration independent from CWD (current working directory). - ---- - - -## `entry` - -`string | [string] | object { <key>: string | [string] } | (function: () => string | [string] | object { <key>: string | [string] })` - -The point or points to enter the application. At this point the application starts executing. If an array is passed all items will be executed. - -A dynamically loaded module is __not__ an entry point. - -Simple rule: one entry point per HTML page. SPA: one entry point, MPA: multiple entry points. - -```js -module.exports = { - //... - entry: { - home: './home.js', - about: './about.js', - contact: './contact.js' - } -}; -``` - - -### Naming - -If a string or array of strings is passed, the chunk is named `main`. If an object is passed, each key is the name of a chunk, and the value describes the entry point for the chunk. - - -### Dynamic entry - -If a function is passed then it will be invoked on every [make](/api/compiler-hooks/#make) event. - -> Note that the make event triggers when webpack starts and for every invalidation when [watching for file changes](/configuration/watch/). - -```js -module.exports = { - //... - entry: () => './demo' -}; -``` - -or - -```js -module.exports = { - //... - entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])) -}; -``` - -For example: you can use dynamic entries to get the actual entries from an external source (remote server, file system content or database): - -__webpack.config.js__ - -``` js -module.exports = { - entry() { - return fetchPathsFromSomeExternalSource(); // returns a promise that will be resolved with something like ['src/main-layout.js', 'src/admin-layout.js'] - } -}; -``` - -When combining with the [`output.library`](/configuration/output#output-library) option: If an array is passed only the last item is exported. - - -# Output - -The top-level `output` key contains set of options instructing webpack on how and where it should output your bundles, assets and anything else you bundle or load with webpack. - - -## `output.auxiliaryComment` - -`string` `object` - -When used in tandem with [`output.library`](#output-library) and [`output.libraryTarget`](#output-librarytarget), this option allows users to insert comments within the export wrapper. To insert the same comment for each `libraryTarget` type, set `auxiliaryComment` to a string: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - library: 'someLibName', - libraryTarget: 'umd', - filename: 'someLibName.js', - auxiliaryComment: 'Test Comment' - } -}; -``` - -which will yield the following: - -__webpack.config.js__ - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - // Test Comment - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require('lodash')); - // Test Comment - else if(typeof define === 'function' && define.amd) - define(['lodash'], factory); - // Test Comment - else if(typeof exports === 'object') - exports['someLibName'] = factory(require('lodash')); - // Test Comment - else - root['someLibName'] = factory(root['_']); -})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { - // ... -}); -``` - -For fine-grained control over each `libraryTarget` comment, pass an object: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - //... - auxiliaryComment: { - root: 'Root Comment', - commonjs: 'CommonJS Comment', - commonjs2: 'CommonJS2 Comment', - amd: 'AMD Comment' - } - } -}; -``` - - -## `output.chunkFilename` - -`string` - -This option determines the name of non-entry chunk files. See [`output.filename`](#output-filename) option for details on the possible values. - -Note that these filenames need to be generated at runtime to send the requests for chunks. Because of this, placeholders like `[name]` and `[chunkhash]` need to add a mapping from chunk id to placeholder value to the output bundle with the webpack runtime. This increases the size and may invalidate the bundle when placeholder value for any chunk changes. - -By default `[id].js` is used or a value inferred from [`output.filename`](#output-filename) (`[name]` is replaced with `[id]` or `[id].` is prepended). - - -## `output.chunkLoadTimeout` - -`integer` - -Number of milliseconds before chunk request expires, defaults to 120 000. This option is supported since webpack 2.6.0. - - -## `output.crossOriginLoading` - -`boolean` `string` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks, by adding script tags. - -Enable [cross-origin](https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-crossorigin) loading of chunks. The following values are accepted... - -`crossOriginLoading: false` - Disable cross-origin loading (default) - -`crossOriginLoading: 'anonymous'` - Enable cross-origin loading __without credentials__ - -`crossOriginLoading: 'use-credentials'` - Enable cross-origin loading __with credentials__ - - -## `output.jsonpScriptType` - -`string` - -Allows customization of the `script` type webpack injects `script` tags into the DOM to download async chunks. The following options are available: - -- `'text/javascript'` (default) -- `'module'`: Use with ES6 ready code. - - -## `output.devtoolFallbackModuleFilenameTemplate` - -`string | function(info)` - -A fallback used when the template string or function above yields duplicates. - -See [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). - - -## `output.devtoolLineToLine` - -`boolean | object` - -> Avoid using this option as it is __deprecated__ and will soon be removed. - -Enables line to line mapping for all or some modules. This produces a simple source map where each line of the generated source is mapped to the same line of the original source. This is a performance optimization and should only be used if all input lines match generated lines. - -Pass a boolean to enable or disable this feature for all modules (defaults to `false`). An object with `test`, `include`, `exclude` is also allowed. For example, to enable this feature for all javascript files within a certain directory: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - devtoolLineToLine: { test: /\.js$/, include: 'src/utilities' } - } -}; -``` - - -## `output.devtoolModuleFilenameTemplate` - -`string | function(info)` - -This option is only used when [`devtool`](/configuration/devtool) uses an options which requires module names. - -Customize the names used in each source map's `sources` array. This can be done by passing a template string or function. For example, when using `devtool: 'eval'`, this is the default: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - devtoolModuleFilenameTemplate: 'webpack://[namespace]/[resource-path]?[loaders]' - } -}; -``` - -The following substitutions are available in template strings (via webpack's internal [`ModuleFilenameHelpers`](https://github.com/webpack/webpack/blob/master/lib/ModuleFilenameHelpers.js)): - -| Template | Description | -| ------------------------ | ----------- | -| [absolute-resource-path] | The absolute filename | -| [all-loaders] | Automatic and explicit loaders and params up to the name of the first loader | -| [hash] | The hash of the module identifier | -| [id] | The module identifier | -| [loaders] | Explicit loaders and params up to the name of the first loader | -| [resource] | The path used to resolve the file and any query params used on the first loader | -| [resource-path] | The path used to resolve the file without any query params | -| [namespace] | The modules namespace. This is usually the library name when building as a library, empty otherwise | - -When using a function, the same options are available camel-cased via the `info` parameter: - -```javascript -module.exports = { - //... - output: { - devtoolModuleFilenameTemplate: info => { - return `webpack:///${info.resourcePath}?${info.loaders}`; - } - } -}; -``` - -If multiple modules would result in the same name, [`output.devtoolFallbackModuleFilenameTemplate`](#output-devtoolfallbackmodulefilenametemplate) is used instead for these modules. - - -## `output.devtoolNamespace` - -`string` - -This option determines the modules namespace used with the [`output.devtoolModuleFilenameTemplate`](#output-devtoolmodulefilenametemplate). When not specified, it will default to the value of: [`output.library`](#output-library). It's used to prevent source file path collisions in source maps when loading multiple libraries built with webpack. - -For example, if you have 2 libraries, with namespaces `library1` and `library2`, which both have a file `./src/index.js` (with potentially different contents), they will expose these files as `webpack://library1/./src/index.js` and `webpack://library2/./src/index.js`. - - -## `output.filename` - -`string` `function` - -This option determines the name of each output bundle. The bundle is written to the directory specified by the [`output.path`](#output-path) option. - -For a single [`entry`](/configuration/entry-context#entry) point, this can be a static name. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: 'bundle.js' - } -}; -``` - -However, when creating multiple bundles via more than one entry point, code splitting, or various plugins, you should use one of the following substitutions to give each bundle a unique name... - -Using entry name: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[name].bundle.js' - } -}; -``` - -Using internal chunk id: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[id].bundle.js' - } -}; -``` - -Using the unique hash generated for every build: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[name].[hash].bundle.js' - } -}; -``` - -Using hashes based on each chunks' content: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[chunkhash].bundle.js' - } -}; -``` - -Using hashes generated for extracted content: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: '[contenthash].bundle.css' - } -}; -``` - -Using function to return the filename: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: (chunkData) => { - return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js'; - }, - } -}; -``` - -Make sure to read the [Caching guide](/guides/caching) for details. There are more steps involved than just setting this option. - -Note this option is called filename but you are still allowed to use something like `'js/[name]/bundle.js'` to create a folder structure. - -Note this option does not affect output files for on-demand-loaded chunks. For these files the [`output.chunkFilename`](#output-chunkfilename) option is used. Files created by loaders also aren't affected. In this case you would have to try the specific loader's available options. - -The following substitutions are available in template strings (via webpack's internal [`TemplatedPathPlugin`](https://github.com/webpack/webpack/blob/master/lib/TemplatedPathPlugin.js)): - -| Template | Description | -| ----------- | ----------------------------------------------------------------------------------- | -| [hash] | The hash of the module identifier | -| [chunkhash] | The hash of the chunk content | -| [name] | The module name | -| [id] | The module identifier | -| [query] | The module query, i.e., the string following `?` in the filename | -| [function] | The function, which can return filename [string] | - -The lengths of `[hash]` and `[chunkhash]` can be specified using `[hash:16]` (defaults to 20). Alternatively, specify [`output.hashDigestLength`](#output-hashdigestlength) to configure the length globally. - -If using a function for this option, the function will be passed an object containing the substitutions in the table above. - -T> When using the [`ExtractTextWebpackPlugin`](/plugins/extract-text-webpack-plugin), use `[contenthash]` to obtain a hash of the extracted file (neither `[hash]` nor `[chunkhash]` work). - - -## `output.hashDigest` - -The encoding to use when generating the hash, defaults to `'hex'`. All encodings from Node.JS' [`hash.digest`](https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding) are supported. Using `'base64'` for filenames might be problematic since it has the character `/` in its alphabet. Likewise `'latin1'` could contain any character. - - -## `output.hashDigestLength` - -The prefix length of the hash digest to use, defaults to `20`. - - -## `output.hashFunction` - -`string|function` - -The hashing algorithm to use, defaults to `'md4'`. All functions from Node.JS' [`crypto.createHash`](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options) are supported. Since `4.0.0-alpha2`, the `hashFunction` can now be a constructor to a custom hash function. You can provide a non-crypto hash function for performance reasons. - -```javascript -module.exports = { - //... - output: { - hashFunction: require('metrohash').MetroHash64 - } -}; -``` - -Make sure that the hashing function will have `update` and `digest` methods available. - -## `output.hashSalt` - -An optional salt to update the hash via Node.JS' [`hash.update`](https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding). - - -## `output.hotUpdateChunkFilename` - -`string` `function` - -Customize the filenames of hot update chunks. See [`output.filename`](#output-filename) option for details on the possible values. - -The only placeholders allowed here are `[id]` and `[hash]`, the default being: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - hotUpdateChunkFilename: '[id].[hash].hot-update.js' - } -}; -``` - -Here is no need to change it. - - -## `output.hotUpdateFunction` - -`function` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading hot updates. - -A JSONP function used to asynchronously load hot-update chunks. - -For details see [`output.jsonpFunction`](#output-jsonpfunction). - - -## `output.hotUpdateMainFilename` - -`string` `function` - -Customize the main hot update filename. See [`output.filename`](#output-filename) option for details on the possible values. - -`[hash]` is the only available placeholder, the default being: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - hotUpdateMainFilename: '[hash].hot-update.json' - } -}; -``` - -Here is no need to change it. - - -## `output.jsonpFunction` - -`string` - -Only used when [`target`](/configuration/target) is web, which uses JSONP for loading on-demand chunks. - -A JSONP function name used to asynchronously load chunks or join multiple initial chunks (SplitChunksPlugin, AggressiveSplittingPlugin). - -This needs to be changed if multiple webpack runtimes (from different compilation) are used on the same webpage. - -If using the [`output.library`](#output-library) option, the library name is automatically appended. - - -## `output.library` - -`string` or `object` (since webpack 3.1.0; for `libraryTarget: 'umd'`) - -How the value of the `output.library` is used depends on the value of the [`output.libraryTarget`](#output-librarytarget) option; please refer to that section for the complete details. Note that the default option for `output.libraryTarget` is `var`, so if the following configuration option is used: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary' - } -}; -``` - -The variable `MyLibrary` will be bound with the return value of your entry file, if the resulting output is included as a script tag in an HTML page. - -W> Note that if an `array` is provided as an `entry` point, only the last module in the array will be exposed. If an `object` is provided, it can be exposed using an `array` syntax (see [this example](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) for details). - -T> Read the [authoring libraries guide](/guides/author-libraries) guide for more information on `output.library` as well as `output.libraryTarget`. - - -## `output.libraryExport` - -`string | string[]` - -Configure which module or modules will be exposed via the `libraryTarget`. It is `undefined` by default, same behaviour will be applied if you set `libraryTarget` to an empty string e.g. `''` it will export the whole (namespace) object. The examples below demonstrate the effect of this config when using `libraryTarget: 'var'`. - -The following configurations are supported: - -`libraryExport: 'default'` - The __default export of your entry point__ will be assigned to the library target: - -```javascript -// if your entry has a default export of `MyDefaultModule` -var MyDefaultModule = _entry_return_.default; -``` - -`libraryExport: 'MyModule'` - The __specified module__ will be assigned to the library target: - -```javascript -var MyModule = _entry_return_.MyModule; -``` - -`libraryExport: ['MyModule', 'MySubModule']` - The array is interpreted as a __path to a module__ to be assigned to the library target: - -```javascript -var MySubModule = _entry_return_.MyModule.MySubModule; -``` - -With the `libraryExport` configurations specified above, the resulting libraries could be utilized as such: - -```javascript -MyDefaultModule.doSomething(); -MyModule.doSomething(); -MySubModule.doSomething(); -``` - - -## `output.libraryTarget` - -`string: 'var'` - -Configure how the library will be exposed. Any one of the following options can be used. Please note that this option works in conjunction with the value assigned to [`output.library`](#output-library). For the following examples, it is assumed that this value is configured as `MyLibrary`. - -T> Note that `_entry_return_` in the example code below is the value returned by the entry point. In the bundle itself, it is the output of the function that is generated by webpack from the entry point. - -### Expose a Variable - -These options assign the return value of the entry point (e.g. whatever the entry point exported) to the name provided by `output.library` at whatever scope the bundle was included at. - -`libraryTarget: 'var'` - (default) When your library is loaded, the __return value of your entry point__ will be assigned to a variable: - -```javascript -var MyLibrary = _entry_return_; - -// In a separate script... -MyLibrary.doSomething(); -``` - -W> When using this option, an empty `output.library` will result in no assignment. - - -`libraryTarget: 'assign'` - This will generate an implied global which has the potential to reassign an existing value (use with caution). - -```javascript -MyLibrary = _entry_return_; -``` - -Be aware that if `MyLibrary` isn't defined earlier your library will be set in global scope. - -W> When using this option, an empty `output.library` will result in a broken output bundle. - - -### Expose Via Object Assignment - -These options assign the return value of the entry point (e.g. whatever the entry point exported) to a specific object under the name defined by `output.library`. - -If `output.library` is not assigned a non-empty string, the default behavior is that all properties returned by the entry point will be assigned to the object as defined for the particular `output.libraryTarget`, via the following code fragment: - -```javascript -(function(e, a) { for(var i in a) { e[i] = a[i]; } }(output.libraryTarget, _entry_return_)); -``` - -W> Note that not setting a `output.library` will cause all properties returned by the entry point to be assigned to the given object; there are no checks against existing property names. - -`libraryTarget: "this"` - The __return value of your entry point__ will be assigned to this under the property named by `output.library`. The meaning of `this` is up to you: - -```javascript -this['MyLibrary'] = _entry_return_; - -// In a separate script... -this.MyLibrary.doSomething(); -MyLibrary.doSomething(); // if this is window -``` - -`libraryTarget: 'window'` - The __return value of your entry point__ will be assigned to the `window` object using the `output.library` value. - -```javascript -window['MyLibrary'] = _entry_return_; - -window.MyLibrary.doSomething(); -``` - - -`libraryTarget: 'global'` - The __return value of your entry point__ will be assigned to the `global` object using the `output.library` value. - -```javascript -global['MyLibrary'] = _entry_return_; - -global.MyLibrary.doSomething(); -``` - - -`libraryTarget: 'commonjs'` - The __return value of your entry point__ will be assigned to the `exports` object using the `output.library` value. As the name implies, this is used in CommonJS environments. - -```javascript -exports['MyLibrary'] = _entry_return_; - -require('MyLibrary').doSomething(); -``` - -### Module Definition Systems - -These options will result in a bundle that comes with a more complete header to ensure compatibility with various module systems. The `output.library` option will take on a different meaning under the following `output.libraryTarget` options. - - -`libraryTarget: 'commonjs2'` - The __return value of your entry point__ will be assigned to the `module.exports`. As the name implies, this is used in CommonJS environments: - -```javascript -module.exports = _entry_return_; - -require('MyLibrary').doSomething(); -``` - -Note that `output.library` is omitted, thus it is not required for this particular `output.libraryTarget`. - -T> Wondering the difference between CommonJS and CommonJS2 is? While they are similar, there are some subtle differences between them that are not usually relevant in the context of webpack. (For further details, please [read this issue](https://github.com/webpack/webpack/issues/1114).) - - -`libraryTarget: 'amd'` - This will expose your library as an AMD module. - -AMD modules require that the entry chunk (e.g. the first script loaded by the `<script>` tag) be defined with specific properties, such as `define` and `require` which is typically provided by RequireJS or any compatible loaders (such as almond). Otherwise, loading the resulting AMD bundle directly will result in an error like `define is not defined`. - -So, with the following configuration... - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary', - libraryTarget: 'amd' - } -}; -``` - -The generated output will be defined with the name "MyLibrary", i.e. - -```javascript -define('MyLibrary', [], function() { - return _entry_return_; -}); -``` - -The bundle can be included as part of a script tag, and the bundle can be invoked like so: - -```javascript -require(['MyLibrary'], function(MyLibrary) { - // Do something with the library... -}); -``` - -If `output.library` is undefined, the following is generated instead. - -```javascript -define([], function() { - return _entry_return_; -}); -``` - -This bundle will not work as expected, or not work at all (in the case of the almond loader) if loaded directly with a `<script>` tag. It will only work through a RequireJS compatible asynchronous module loader through the actual path to that file, so in this case, the `output.path` and `output.filename` may become important for this particular setup if these are exposed directly on the server. - - -`libraryTarget: 'amd-require'` - This packages your output with an immediately-executed AMD `require(dependencies, factory)` wrapper. - -The `'amd-require'` target allows for the use of AMD dependencies without needing a separate later invocation. As with the `'amd'` target, this depends on the appropriate [`require` function](https://github.com/amdjs/amdjs-api/blob/master/require.md) being available in the environment in which the webpack output is loaded. - -With this target, the library name is ignored. - - -`libraryTarget: 'umd'` - This exposes your library under all the module definitions, allowing it to work with CommonJS, AMD and as global variable. Take a look at the [UMD Repository](https://github.com/umdjs/umd) to learn more. - -In this case, you need the `library` property to name your module: - -```javascript -module.exports = { - //... - output: { - library: 'MyLibrary', - libraryTarget: 'umd' - } -}; -``` - -And finally the output is: - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports['MyLibrary'] = factory(); - else - root['MyLibrary'] = factory(); -})(typeof self !== 'undefined' ? self : this, function() { - return _entry_return_; -}); -``` - -Note that omitting `library` will result in the assignment of all properties returned by the entry point be assigned directly to the root object, as documented under the [object assignment section](#expose-via-object-assignment). Example: - -```javascript -module.exports = { - //... - output: { - libraryTarget: 'umd' - } -}; -``` - -The output will be: - -```javascript -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else { - var a = factory(); - for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; - } -})(typeof self !== 'undefined' ? self : this, function() { - return _entry_return_; -}); -``` - -Since webpack 3.1.0, you may specify an object for `library` for differing names per targets: - -```javascript -module.exports = { - //... - output: { - library: { - root: 'MyLibrary', - amd: 'my-library', - commonjs: 'my-common-library' - }, - libraryTarget: 'umd' - } -}; -``` - -Module proof library. - - -### Other Targets - -`libraryTarget: 'jsonp'` - This will wrap the return value of your entry point into a jsonp wrapper. - -``` javascript -MyLibrary(_entry_return_); -``` - -The dependencies for your library will be defined by the [`externals`](/configuration/externals/) config. - - -## `output.path` - -`string` - -The output directory as an __absolute__ path. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - path: path.resolve(__dirname, 'dist/assets') - } -}; -``` - -Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. - - -## `output.pathinfo` - -`boolean` - -Tells webpack to include comments in bundles with information about the contained modules. This option defaults to `true` in `development` and `false` in `production` [mode](/concepts/mode/) respectively. - -W> While the data this comments can provide is very useful during development when reading the generated code, it __should not__ be used in production. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - pathinfo: true - } -}; -``` - -Note it also adds some info about tree shaking to the generated bundle. - - -## `output.publicPath` - -`string: ''` `function` - -This is an important option when using on-demand-loading or loading external resources like images, files, etc. If an incorrect value is specified you'll receive 404 errors while loading these resources. - -This option specifies the __public URL__ of the output directory when referenced in a browser. A relative URL is resolved relative to the HTML page (or `<base>` tag). Server-relative URLs, protocol-relative URLs or absolute URLs are also possible and sometimes required, i. e. when hosting assets on a CDN. - -The value of the option is prefixed to every URL created by the runtime or loaders. Because of this __the value of this option ends with `/`__ in most cases. - -Simple rule: The URL of your [`output.path`](#output-path) from the view of the HTML page. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - path: path.resolve(__dirname, 'public/assets'), - publicPath: 'https://cdn.example.com/assets/' - } -}; -``` - -For this configuration: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - publicPath: '/assets/', - chunkFilename: '[id].chunk.js' - } -}; -``` - -A request to a chunk will look like `/assets/4.chunk.js`. - -A loader outputting HTML might emit something like this: - -```html -<link href="/assets/spinner.gif" /> -``` - -or when loading an image in CSS: - -```css -background-image: url(/assets/spinner.gif); -``` - -The webpack-dev-server also takes a hint from `publicPath`, using it to determine where to serve the output files from. - -Note that `[hash]` in this parameter will be replaced with an hash of the compilation. See the [Caching guide](/guides/caching) for details. - -Examples: - -```javascript -module.exports = { - //... - output: { - // One of the below - publicPath: 'https://cdn.example.com/assets/', // CDN (always HTTPS) - publicPath: '//cdn.example.com/assets/', // CDN (same protocol) - publicPath: '/assets/', // server-relative - publicPath: 'assets/', // relative to HTML page - publicPath: '../assets/', // relative to HTML page - publicPath: '', // relative to HTML page (same directory) - } -}; -``` - -In cases where the `publicPath` of output files can't be known at compile time, it can be left blank and set dynamically at runtime in the entry file using the [free variable](https://stackoverflow.com/questions/12934929/what-are-free-variables) `__webpack_public_path__`. - -```javascript -__webpack_public_path__ = myRuntimePublicPath; - -// rest of your application entry -``` - -See [this discussion](https://github.com/webpack/webpack/issues/2776#issuecomment-233208623) for more information on `__webpack_public_path__`. - - -## `output.sourceMapFilename` - -`string` - -This option is only used when [`devtool`](/configuration/devtool) uses a SourceMap option which writes an output file. - -Configure how source maps are named. By default `'[file].map'` is used. - -The `[name]`, `[id]`, `[hash]` and `[chunkhash]` substitutions from [#output-filename](#output-filename) can be used. In addition to those, you can use substitutions listed below. The `[file]` placeholder is replaced with the filename of the original file. We recommend __only using the `[file]` placeholder__, as the other placeholders won't work when generating SourceMaps for non-chunk files. - -| Template | Description | -| -------------------------- | ----------------------------------------------------------------------------------- | -| [file] | The module filename | -| [filebase] | The module [basename](https://nodejs.org/api/path.html#path_path_basename_path_ext) | - - -## `output.sourcePrefix` - -`string` - -Change the prefix for each line in the output bundles. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - sourcePrefix: '\t' - } -}; -``` - -Note by default an empty string is used. Using some kind of indentation makes bundles look more pretty, but will cause issues with multi-line strings. - -There is no need to change it. - - -## `output.strictModuleExceptionHandling` - -`boolean` - -Tell webpack to remove a module from the module instance cache (`require.cache`) if it throws an exception when it is `require`d. - -It defaults to `false` for performance reasons. - -When set to `false`, the module is not removed from cache, which results in the exception getting thrown only on the first `require` call (making it incompatible with node.js). - -For instance, consider `module.js`: - -```javascript -throw new Error('error'); -``` - -With `strictModuleExceptionHandling` set to `false`, only the first `require` throws an exception: - -```javascript -// with strictModuleExceptionHandling = false -require('module'); // <- throws -require('module'); // <- doesn't throw -``` - -Instead, with `strictModuleExceptionHandling` set to `true`, all `require`s of this module throw an exception: - -```javascript -// with strictModuleExceptionHandling = true -require('module'); // <- throws -require('module'); // <- also throws -``` - - -## `output.umdNamedDefine` - -`boolean` - -When using `libraryTarget: "umd"`, setting: - -```javascript -module.exports = { - //... - output: { - umdNamedDefine: true - } -}; -``` - -will name the AMD module of the UMD build. Otherwise an anonymous `define` is used. - - -# Module - -These options determine how the [different types of modules](/concepts/modules) within a project will be treated. - - -## `module.noParse` - -`RegExp | [RegExp] | function | string | [string]` - -Prevent webpack from parsing any files matching the given regular expression(s). Ignored files __should not__ have calls to `import`, `require`, `define` or any other importing mechanism. This can boost build performance when ignoring large libraries. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - noParse: /jquery|lodash/, - } -}; -``` - -```javascript -module.exports = { - //... - module: { - noParse: (content) => /jquery|lodash/.test(content) - } -}; -``` - - -## `module.rules` - -`[Rule]` - -An array of [Rules](#rule) which are matched to requests when modules are created. These rules can modify how the module is created. They can apply loaders to the module, or modify the parser. - - -## Rule - -`object` - -A Rule can be separated into three parts — Conditions, Results and nested Rules. - - -### Rule Conditions - -There are two input values for the conditions: - -1. The resource: An absolute path to the file requested. It's already resolved according to the [`resolve` rules](/configuration/resolve). - -2. The issuer: An absolute path to the file of the module which requested the resource. It's the location of the import. - -__Example:__ When we `import './style.css'` within `app.js`, the resource is `/path/to/style.css` and the issuer is `/path/to/app.js`. - -In a Rule the properties [`test`](#rule-test), [`include`](#rule-include), [`exclude`](#rule-exclude) and [`resource`](#rule-resource) are matched with the resource and the property [`issuer`](#rule-issuer) is matched with the issuer. - -When using multiple conditions, all conditions must match. - -W> Be careful! The resource is the _resolved_ path of the file, which means symlinked resources are the real path _not_ the symlink location. This is good to remember when using tools that symlink packages (like `npm link`), common conditions like `/node_modules/` may inadvertently miss symlinked files. Note that you can turn off symlink resolving (so that resources are resolved to the symlink path) via [`resolve.symlinks`](/configuration/resolve#resolve-symlinks). - - -### Rule results - -Rule results are used only when the Rule condition matches. - -There are two output values of a Rule: - -1. Applied loaders: An array of loaders applied to the resource. -2. Parser options: An options object which should be used to create the parser for this module. - -These properties affect the loaders: [`loader`](#rule-loader), [`options`](#rule-options-rule-query), [`use`](#rule-use). - -For compatibility also these properties: [`query`](#rule-options-rule-query), [`loaders`](#rule-loaders). - -The [`enforce`](#rule-enforce) property affects the loader category. Whether it's a normal, pre- or post- loader. - -The [`parser`](#rule-parser) property affects the parser options. - - -## Nested rules - -Nested rules can be specified under the properties [`rules`](#rule-rules) and [`oneOf`](#rule-oneof). - -These rules are evaluated when the Rule condition matches. - - -## `Rule.enforce` - -`string` - -Possible values: `'pre' | 'post'` - -Specifies the category of the loader. No value means normal loader. - -There is also an additional category "inlined loader" which are loaders applied inline of the import/require. - -There are two phases that all loaders enter one after the other: - -1. __Pitching__ phase: the pitch method on loaders is called in the order `post, inline, normal, pre`. See [Pitching Loader](/api/loaders/#pitching-loader) for details. -2. __Normal__ phase: the normal method on loaders is executed in the order `pre, normal, inline, post`. Transformation on the source code of a module happens in this phase. - -All normal loaders can be omitted (overridden) by prefixing `!` in the request. - -All normal and pre loaders can be omitted (overridden) by prefixing `-!` in the request. - -All normal, post and pre loaders can be omitted (overridden) by prefixing `!!` in the request. - -Inline loaders and `!` prefixes should not be used as they are non-standard. They may be use by loader generated code. - - -## `Rule.exclude` - -`Rule.exclude` is a shortcut to `Rule.resource.exclude`. If you supply a `Rule.exclude` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.exclude`](#condition) for details. - - -## `Rule.include` - -`Rule.include` is a shortcut to `Rule.resource.include`. If you supply a `Rule.include` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.include`](#condition) for details. - - -## `Rule.issuer` - -A [`Condition`](#condition) to match against the module that issued the request. In the following example, the `issuer` for the `a.js` request would be the path to the `index.js` file. - -__index.js__ - -```javascript -import A from './a.js'; -``` - -This option can be used to apply loaders to the dependencies of a specific module or set of modules. - - -## `Rule.loader` - -`Rule.loader` is a shortcut to `Rule.use: [ { loader } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.loader`](#useentry) for details. - - -## `Rule.loaders` - -W> This option is __deprecated__ in favor of `Rule.use`. - -`Rule.loaders` is an alias to `Rule.use`. See [`Rule.use`](#rule-use) for details. - - -## `Rule.oneOf` - -An array of [`Rules`](#rule) from which only the first matching Rule is used when the Rule matches. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - oneOf: [ - { - resourceQuery: /inline/, // foo.css?inline - use: 'url-loader' - }, - { - resourceQuery: /external/, // foo.css?external - use: 'file-loader' - } - ] - } - ] - } -}; -``` - -## `Rule.options` / `Rule.query` - -`Rule.options` and `Rule.query` are shortcuts to `Rule.use: [ { options } ]`. See [`Rule.use`](#rule-use) and [`UseEntry.options`](#useentry) for details. - -W> `Rule.query` is deprecated in favor of `Rule.options` and `UseEntry.options`. - - -## `Rule.parser` - -An object with parser options. All applied parser options are merged. - -Parsers may inspect these options and disable or reconfigure themselves accordingly. Most of the default plugins interpret the values as follows: - -- Setting the option to `false` disables the parser. -- Setting the option to `true` or leaving it `undefined` enables the parser. - -However, parser plugins may accept more than just a boolean. For example, the internal `NodeStuffPlugin` can accept an object instead of `true` to add additional options for a particular Rule. - -__Examples__ (parser options by the default plugins): - -```js-with-links -module.exports = { - //... - module: { - rules: [ - { - //... - parser: { - amd: false, // disable AMD - commonjs: false, // disable CommonJS - system: false, // disable SystemJS - harmony: false, // disable ES2015 Harmony import/export - requireInclude: false, // disable require.include - requireEnsure: false, // disable require.ensure - requireContext: false, // disable require.context - browserify: false, // disable special handling of Browserify bundles - requireJs: false, // disable requirejs.* - node: false, // disable __dirname, __filename, module, require.extensions, require.main, etc. - node: {...} // reconfigure [node](/configuration/node) layer on module level - } - } - ] - } -} -``` - - -## `Rule.resource` - -A [`Condition`](#condition) matched with the resource. You can either supply a `Rule.resource` option or use the shortcut options `Rule.test`, `Rule.exclude`, and `Rule.include`. See details in [`Rule` conditions](#rule-conditions). - - -## `Rule.resourceQuery` - -A [`Condition`](#condition) matched with the resource query. This option is used to test against the query section of a request string (i.e. from the question mark onwards). If you were to `import Foo from './foo.css?inline'`, the following condition would match: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - resourceQuery: /inline/, - use: 'url-loader' - } - ] - } -}; -``` - - -## `Rule.rules` - -An array of [`Rules`](#rule) that is also used when the Rule matches. - - -## `Rule.sideEffects` - -`bool` - -Indicate what parts of the module contain side effects. See [Tree Shaking](/guides/tree-shaking/#mark-the-file-as-side-effect-free) for details. - - -## `Rule.test` - -`Rule.test` is a shortcut to `Rule.resource.test`. If you supply a `Rule.test` option, you cannot also supply a `Rule.resource`. See [`Rule.resource`](#rule-resource) and [`Condition.test`](#condition) for details. - - -## `Rule.type` - -`string` - -Possible values: `'javascript/auto' | 'javascript/dynamic' | 'javascript/esm' | 'json' | 'webassembly/experimental'` - -`Rule.type` sets the type for a matching module. This prevents defaultRules and their default importing behaviors from occurring. For example, if you want to load a `.json` file through a custom loader, you'd need to set the `type` to `javascript/auto` to bypass webpack's built-in json importing. (See [v4.0 changelog](https://github.com/webpack/webpack/releases/tag/v4.0.0) for more details) - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - //... - { - test: /\.json$/, - type: 'javascript/auto', - loader: 'custom-json-loader' - } - ] - } -}; -``` - - -## `Rule.use` - -A list of [UseEntries](#useentry) which are applied to modules. Each entry specifies a loader to be used. - -Passing a string (i.e. `use: [ 'style-loader' ]`) is a shortcut to the loader property (i.e. `use: [ { loader: 'style-loader '} ]`). - -Loaders can be chained by passing multiple loaders, which will be applied from right to left (last to first configured). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - //... - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1 - } - }, - { - loader: 'less-loader', - options: { - noIeCompat: true - } - } - ] - } - ] - } -}; -``` - -See [UseEntry](#useentry) for details. - - -## `Condition` - -Conditions can be one of these: - -- A string: To match the input must start with the provided string. I. e. an absolute directory path, or absolute path to the file. -- A RegExp: It's tested with the input. -- A function: It's called with the input and must return a truthy value to match. -- An array of Conditions: At least one of the Conditions must match. -- An object: All properties must match. Each property has a defined behavior. - -`{ test: Condition }`: The Condition must match. The convention is to provide a RegExp or array of RegExps here, but it's not enforced. - -`{ include: Condition }`: The Condition must match. The convention is to provide a string or array of strings here, but it's not enforced. - -`{ exclude: Condition }`: The Condition must NOT match. The convention is to provide a string or array of strings here, but it's not enforced. - -`{ and: [Condition] }`: All Conditions must match. - -`{ or: [Condition] }`: Any Condition must match. - -`{ not: [Condition] }`: All Conditions must NOT match. - -__Example:__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - test: /\.css$/, - include: [ - path.resolve(__dirname, 'app/styles'), - path.resolve(__dirname, 'vendor/styles') - ] - } - ] - } -}; -``` - - -## `UseEntry` - -`object` - -It must have a `loader` property being a string. It is resolved relative to the configuration [`context`](/configuration/entry-context#context) with the loader resolving options ([resolveLoader](/configuration/resolve#resolveloader)). - -It can have an `options` property being a string or object. This value is passed to the loader, which should interpret it as loader options. - -For compatibility a `query` property is also possible, which is an alias for the `options` property. Use the `options` property instead. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - rules: [ - { - loader: 'css-loader', - options: { - modules: true - } - } - ] - } -}; -``` - -Note that webpack needs to generate a unique module identifier from the resource and all loaders including options. It tries to do this with a `JSON.stringify` of the options object. This is fine in 99.9% of cases, but may be not unique if you apply the same loaders with different options to the resource and the options have some stringified values. - -It also breaks if the options object cannot be stringified (i.e. circular JSON). Because of this you can have a `ident` property in the options object which is used as unique identifier. - - -## Module Contexts - -> Avoid using these options as they are __deprecated__ and will soon be removed. - -These options describe the default settings for the context created when a dynamic dependency is encountered. - -Example for an `unknown` dynamic dependency: `require`. - -Example for an `expr` dynamic dependency: `require(expr)`. - -Example for an `wrapped` dynamic dependency: `require('./templates/' + expr)`. - -Here are the available options with their [defaults](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js): - -__webpack.config.js__ - -```javascript -module.exports = { - //... - module: { - exprContextCritical: true, - exprContextRecursive: true, - exprContextRegExp: false, - exprContextRequest: '.', - unknownContextCritical: true, - unknownContextRecursive: true, - unknownContextRegExp: false, - unknownContextRequest: '.', - wrappedContextCritical: false, - wrappedContextRecursive: true, - wrappedContextRegExp: /.*/, - strictExportPresence: false // since webpack 2.3.0 - } -}; -``` - -T> You can use the `ContextReplacementPlugin` to modify these values for individual dependencies. This also removes the warning. - -A few use cases: - -- Warn for dynamic dependencies: `wrappedContextCritical: true`. -- `require(expr)` should include the whole directory: `exprContextRegExp: /^\.\//` -- `require('./templates/' + expr)` should not include subdirectories by default: `wrappedContextRecursive: false` -- `strictExportPresence` makes missing exports an error instead of warning - - -# Resolve - -These options change how modules are resolved. webpack provides reasonable defaults, but it is possible to change the resolving in detail. Have a look at [Module Resolution](/concepts/module-resolution) for more explanation of how the resolver works. - - -## `resolve` - -`object` - -Configure how modules are resolved. For example, when calling `import "lodash"` in ES2015, the `resolve` options can change where webpack goes to look for `"lodash"` (see [`modules`](#resolve-modules)). - - -### `resolve.alias` - -`object` - -Create aliases to `import` or `require` certain modules more easily. For example, to alias a bunch of commonly used `src/` folders: - -```js -module.exports = { - //... - resolve: { - alias: { - Utilities: path.resolve(__dirname, 'src/utilities/'), - Templates: path.resolve(__dirname, 'src/templates/') - } - } -}; -``` - -Now, instead of using relative paths when importing like so: - -```js -import Utility from '../../utilities/utility'; -``` - -you can use the alias: - -```js -import Utility from 'Utilities/utility'; -``` - -A trailing `$` can also be added to the given object's keys to signify an exact match: - -```js -module.exports = { - //... - resolve: { - alias: { - xyz$: path.resolve(__dirname, 'path/to/file.js') - } - } -}; -``` - -which would yield these results: - -```js -import Test1 from 'xyz'; // Exact match, so path/to/file.js is resolved and imported -import Test2 from 'xyz/file.js'; // Not an exact match, normal resolution takes place -``` - -The following table explains other cases: - -| `alias:` | `import "xyz"` | `import "xyz/file.js"` | -| ----------------------------------- | ------------------------------------- | ----------------------------------- | -| `{}` | `/abc/node_modules/xyz/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | error | -| `{ xyz$: "/abs/path/to/file.js" }` | `/abs/path/to/file.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "./dir/file.js" }` | `/abc/dir/file.js` | error | -| `{ xyz$: "./dir/file.js" }` | `/abc/dir/file.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "/some/dir" }` | `/some/dir/index.js` | `/some/dir/file.js` | -| `{ xyz$: "/some/dir" }` | `/some/dir/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "./dir" }` | `/abc/dir/index.js` | `/abc/dir/file.js` | -| `{ xyz: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/modu/file.js` | -| `{ xyz$: "modu" }` | `/abc/node_modules/modu/index.js` | `/abc/node_modules/xyz/file.js` | -| `{ xyz: "modu/some/file.js" }` | `/abc/node_modules/modu/some/file.js` | error | -| `{ xyz: "modu/dir" }` | `/abc/node_modules/modu/dir/index.js` | `/abc/node_modules/dir/file.js` | -| `{ xyz: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/dir/file.js` | -| `{ xyz$: "xyz/dir" }` | `/abc/node_modules/xyz/dir/index.js` | `/abc/node_modules/xyz/file.js` | - -`index.js` may resolve to another file if defined in the `package.json`. - -`/abc/node_modules` may resolve in `/node_modules` too. - - -### `resolve.aliasFields` - -`array` - -Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec). Default: - -```js -module.exports = { - //... - resolve: { - aliasFields: ['browser'] - } -}; -``` - - -### `resolve.cacheWithContext` - -`boolean` (since webpack 3.1.0) - -If unsafe cache is enabled, includes `request.context` in the cache key. This option is taken into account by the [`enhanced-resolve`](https://github.com/webpack/enhanced-resolve/) module. Since webpack 3.1.0 context in resolve caching is ignored when resolve or resolveLoader plugins are provided. This addresses a performance regression. - - -### `resolve.descriptionFiles` - -`array` - -The JSON files to use for descriptions. Default: - -```js -module.exports = { - //... - resolve: { - descriptionFiles: ['package.json'] - } -}; -``` - - -### `resolve.enforceExtension` - -`boolean` - -If `true`, it will not allow extension-less files. So by default `require('./foo')` works if `./foo` has a `.js` extension, but with this enabled only `require('./foo.js')` will work. Default: - -```js -module.exports = { - //... - resolve: { - enforceExtension: false - } -}; -``` - - -### `resolve.enforceModuleExtension` - -`boolean` - -Whether to require to use an extension for modules (e.g. loaders). Default: - -```js -module.exports = { - //... - resolve: { - enforceModuleExtension: false - } -}; -``` - - -### `resolve.extensions` - -`array` - -Automatically resolve certain extensions. This defaults to: - -```js -module.exports = { - //... - resolve: { - extensions: ['.wasm', '.mjs', '.js', '.json'] - } -}; -``` - -which is what enables users to leave off the extension when importing: - -```js -import File from '../path/to/file'; -``` - -W> Using this will __override the default array__, meaning that webpack will no longer try to resolve modules using the default extensions. For modules that are imported with their extension, e.g. `import SomeFile from "./somefile.ext"`, to be properly resolved, a string containing "\*" must be included in the array. - - -### `resolve.mainFields` - -`array` - -When importing from an npm package, e.g. `import * as D3 from "d3"`, this option will determine which fields in its `package.json` are checked. The default values will vary based upon the [`target`](/concepts/targets) specified in your webpack configuration. - -When the `target` property is set to `webworker`, `web`, or left unspecified: - - -```js -module.exports = { - //... - resolve: { - mainFields: ['browser', 'module', 'main'] - } -}; -``` - -For any other target (including `node`): - -```js -module.exports = { - //... - resolve: { - mainFields: ['module', 'main'] - } -}; -``` - -For example, the `package.json` of [D3](https://d3js.org/) contains these fields: - -```json -{ - "main": "build/d3.Node.js", - "browser": "build/d3.js", - "module": "index" -} -``` - -This means that when we `import * as D3 from "d3"` this will really resolve to the file in the `browser` property. The `browser` property takes precedence here because it's the first item in `mainFields`. Meanwhile, a Node.js application bundled by webpack will resolve by default to the file in the `module` field. - - -### `resolve.mainFiles` - -`array` - -The filename to be used while resolving directories. Default: - -```js -module.exports = { - //... - resolve: { - mainFiles: ['index'] - } -}; -``` - - -### `resolve.modules` - -`array` - -Tell webpack what directories should be searched when resolving modules. - -Absolute and relative paths can both be used, but be aware that they will behave a bit differently. - -A relative path will be scanned similarly to how Node scans for `node_modules`, by looking through the current directory as well as its ancestors (i.e. `./node_modules`, `../node_modules`, and on). - -With an absolute path, it will only search in the given directory. - -`resolve.modules` defaults to: - -```js -module.exports = { - //... - resolve: { - modules: ['node_modules'] - } -}; -``` - -If you want to add a directory to search in that takes precedence over `node_modules/`: - -```js -module.exports = { - //... - resolve: { - modules: [path.resolve(__dirname, 'src'), 'node_modules'] - } -}; -``` - - -### `resolve.unsafeCache` - -`regex` `array` `boolean` - -Enable aggressive, but __unsafe__, caching of modules. Passing `true` will cache everything. Default: - -```js -module.exports = { - //... - resolve: { - unsafeCache: true - } -}; -``` - -A regular expression, or an array of regular expressions, can be used to test file paths and only cache certain modules. For example, to only cache utilities: - -```js -module.exports = { - //... - resolve: { - unsafeCache: /src\/utilities/ - } -}; -``` - -W> Changes to cached paths may cause failure in rare cases. - - -### `resolve.plugins` - -A list of additional resolve plugins which should be applied. It allows plugins such as [`DirectoryNamedWebpackPlugin`](https://www.npmjs.com/package/directory-named-webpack-plugin). - -```js -module.exports = { - //... - resolve: { - plugins: [ - new DirectoryNamedWebpackPlugin() - ] - } -}; -``` - - -### `resolve.symlinks` - -`boolean` - -Whether to resolve symlinks to their symlinked location. - -When enabled, symlinked resources are resolved to their _real_ path, not their symlinked location. Note that this may cause module resolution to fail when using tools that symlink packages (like `npm link`). - -`resolve.symlinks` defaults to: - -```js -module.exports = { - //... - resolve: { - symlinks: true - } -}; -``` - - -### `resolve.cachePredicate` - -`function` - -A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. Default: - -```js -module.exports = { - //... - resolve: { - cachePredicate: function() { return true; } - } -}; -``` - - -## `resolveLoader` - -`object` - -This set of options is identical to the `resolve` property set above, but is used only to resolve webpack's [loader](/concepts/loaders) packages. Default: - -```js -module.exports = { - //... - resolveLoader: { - modules: [ 'node_modules' ], - extensions: [ '.js', '.json' ], - mainFields: [ 'loader', 'main' ] - } -}; -``` - -T> Note that you can use alias here and other features familiar from resolve. For example `{ txt: 'raw-loader' }` would shim `txt!templates/demo.txt` to use `raw-loader`. - - -### `resolveLoader.moduleExtensions` - -`array` - -The extensions/suffixes that are used when resolving loaders. Since version two, we [strongly recommend](/migrate/3/#automatic-loader-module-name-extension-removed) using the full name, e.g. `example-loader`, as much as possible for clarity. However, if you really wanted to exclude the `-loader` bit, i.e. just use `example`, you can use this option to do so: - -```js -module.exports = { - //... - resolveLoader: { - moduleExtensions: [ '-loader' ] - } -}; -``` - - -# Optimization - -Since version 4 webpack runs optimizations for you depending on the chosen [`mode`](/concepts/mode/), still all optimizations are available for manual configuration and overrides. - - -## `optimization.minimize` - -`boolean` - -Tell webpack to minimize the bundle using the [TerserPlugin](/plugins/terser-webpack-plugin/). - -This is `true` by default in `production` mode. - -__webpack.config.js__ - - -```js -module.exports = { - //... - optimization: { - minimize: false - } -}; -``` - -T> Learn how [mode](/concepts/mode/) works. - -## `optimization.minimizer` - -`[TerserPlugin]` - -Allows you to override the default minimizer by providing a different one or more customized [TerserPlugin](/plugins/terser-webpack-plugin/) instances. - -__webpack.config.js__ - - -```js -const TerserPlugin = require('terser-webpack-plugin'); - -module.exports = { - //... - optimization: { - minimizer: [ - new TerserPlugin({ /* your config */ }) - ] - } -}; -``` - -## `optimization.splitChunks` - -`object` - -By default webpack v4+ provides new common chunks strategies out of the box for dynamically imported modules. See available options for configuring this behavior in the [SplitChunksPlugin](/plugins/split-chunks-plugin/) page. - -## `optimization.runtimeChunk` - -`object` `string` `boolean` - -Setting `optimization.runtimeChunk` to `true` or `"multiple"` adds an additional chunk to each entrypoint containing only the runtime. This setting is an alias for: - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: entrypoint => `runtime~${entrypoint.name}` - } - } -}; -``` - -The value `"single"` instead creates a runtime file to be shared for all generated chunks. This setting is an alias for: - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: 'runtime' - } - } -}; -``` - -By setting `optimization.runtimeChunk` to `object` it is only possible to provide the `name` property which stands for the name or name factory for the runtime chunks. - -Default is `false`: each entry chunk embeds runtime. - -W> Imported modules are initialized for each runtime chunk separately, so if you include multiple entry points on a page, beware of this behavior. You will probably want to set it to `single` or use another configuration that allows you to only have one runtime instance. - -__webpack.config.js__ - - -```js -module.exports = { - //... - optimization: { - runtimeChunk: { - name: entrypoint => `runtimechunk~${entrypoint.name}` - } - } -}; -``` - -## `optimization.noEmitOnErrors` - -`boolean` - -Use the `optimization.noEmitOnErrors` to skip the emitting phase whenever there are errors while compiling. This ensures that no erroring assets are emitted. The `emitted` flag in the stats is `false` for all assets. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - noEmitOnErrors: true - } -}; -``` - -W> If you are using webpack [CLI](/api/cli/), the webpack process will not exit with an error code while this plugin is enabled. If you want webpack to "fail" when using the CLI, please check out the [`bail` option](/api/cli/#advanced-options). - -## `optimization.namedModules` - -`boolean: false` - -Tells webpack to use readable module identifiers for better debugging. When `optimization.namedModules` is not set in webpack config, webpack will enable it by default for [mode](/concepts/mode/) `development` and disable for [mode](/concepts/mode/) `production`. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - namedModules: true - } -}; -``` - -## `optimization.namedChunks` - -`boolean: false` - -Tells webpack to use readable chunk identifiers for better debugging. This option is enabled by default for [mode](/concepts/mode/) `development` and disabled for [mode](/concepts/mode/) `production` if no option is provided in webpack config. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - namedChunks: true - } -}; -``` - -## `optimization.moduleIds` - -`bool: false` `string: natural, named, hashed, size, total-size` - -Tells webpack which algorithm to use when choosing module ids. Setting `optimization.moduleIds` to `false` tells webpack that none of built-in algorithms should be used, as custom one can be provided via plugin. By default `optimization.moduleIds` is set to `false`. - -The following string values are supported: - -Option | Description ---------------------- | ----------------------- -`natural` | Numeric ids in order of usage. -`named` | Readable ids for better debugging. -`hashed` | Short hashes as ids for better long term caching. -`size` | Numeric ids focused on minimal initial download size. -`total-size` | numeric ids focused on minimal total download size. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - moduleIds: 'hashed' - } -}; -``` - -## `optimization.nodeEnv` - -`string` `bool: false` - -Tells webpack to set `process.env.NODE_ENV` to a given string value. `optimization.nodeEnv` uses [DefinePlugin](/plugins/define-plugin/) unless set to `false`. `optimization.nodeEnv` __defaults__ to [mode](/concepts/mode/) if set, else falls back to `"production"`. - -Possible values: - -- any string: the value to set `process.env.NODE_ENV` to. -- false: do not modify/set the value of `process.env.NODE_ENV`. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - nodeEnv: 'production' - } -}; -``` - -## `optimization.mangleWasmImports` - -`bool: false` - -When set to `true` tells webpack to reduce the size of WASM by changing imports to shorter strings. It mangles module and export names. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - mangleWasmImports: true - } -}; -``` - -## `optimization.removeAvailableModules` - -`bool: true` - -Tells webpack to detect and remove modules from chunks when these modules are already included in all parents. Setting `optimization.removeAvailableModules` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - removeAvailableModules: false - } -}; -``` - -## `optimization.removeEmptyChunks` - -`bool: true` - -Tells webpack to detect and remove chunks which are empty. Setting `optimization.removeEmptyChunks` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - removeEmptyChunks: false - } -}; -``` - -## `optimization.mergeDuplicateChunks` - -`bool: true` - -Tells webpack to merge chunks which contain the same modules. Setting `optimization.mergeDuplicateChunks` to `false` will disable this optimization. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - mergeDuplicateChunks: false - } -}; -``` - -## `optimization.flagIncludedChunks` - -`bool` - -Tells webpack to determine and flag chunks which are subsets of other chunks in a way that subsets don’t have to be loaded when the bigger chunk has been already loaded. By default `optimization.flagIncludedChunks` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - flagIncludedChunks: true - } -}; -``` - -## `optimization.occurrenceOrder` - -`bool` - -Tells webpack to figure out an order of modules which will result in the smallest initial bundle. By default `optimization.occurrenceOrder` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - occurrenceOrder: false - } -}; -``` - -## `optimization.providedExports` - -`bool` - -Tells webpack to figure out which exports are provided by modules to generate more efficient code for `export * from ...`. By default `optimization.providedExports` is enabled. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - providedExports: false - } -}; -``` - -## `optimization.usedExports` - -`bool` - -Tells webpack to determine used exports for each module. This depends on [`optimization.providedExports`](#optimization-occurrenceorder). Information collected by `optimization.usedExports` is used by other optimizations or code generation i.e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible. -Dead code elimination in minimizers will benefit from this and can remove unused exports. -By default `optimization.usedExports` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - usedExports: true - } -}; -``` - -## `optimization.concatenateModules` - -`bool` - -Tells webpack to find segments of the module graph which can be safely concatenated into a single module. Depends on [`optimization.providedExports`](#optimization-providedexports) and [`optimization.usedExports`](#optimization-usedexports). -By default `optimization.concatenateModules` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - concatenateModules: true - } -}; -``` - -## `optimization.sideEffects` - -`bool` - -Tells webpack to recognise the [`sideEffects`](https://github.com/webpack/webpack/blob/master/examples/side-effects/README.md) flag in `package.json` or rules to skip over modules which are flagged to contain no side effects when exports are not used. - -__package.json__ - -``` json -{ - "name": "awesome npm module", - "version": "1.0.0", - "sideEffects": false -} -``` - -T> Please note that `sideEffects` should be in the npm module's `package.json` file and doesn't mean that you need to set `sideEffects` to `false` in your own project's `package.json` which requires that big module. - -`optimization.sideEffects` depends on [`optimization.providedExports`](#optimization-providedexports) to be enabled. This dependency has a build time cost, but eliminating modules has positive impact on performance because of less code generation. Effect of this optimization depends on your codebase, try it for possible performance wins. - -By default `optimization.sideEffects` is enabled in `production` [mode](/concepts/mode/) and disabled elsewise. - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - sideEffects: true - } -}; -``` - -## `optimization.portableRecords` - -`bool` - -`optimization.portableRecords` tells webpack to generate records with relative paths to be able to move the context folder. - -By default `optimization.portableRecords` is disabled. Automatically enabled if at least one of the records options provided to webpack config: [`recordsPath`](/configuration/other-options/#recordspath), [`recordsInputPath`](/configuration/other-options/#recordsinputpath), [`recordsOutputPath`](/configuration/other-options/#recordsoutputpath). - -__webpack.config.js__ - -```js -module.exports = { - //... - optimization: { - portableRecords: true - } -}; -``` - - -# Plugins - -The `plugins` option is used to customize the webpack build process in a variety of ways. webpack comes with a variety built-in plugins available under `webpack.[plugin-name]`. See [Plugins page](/plugins) for a list of plugins and documentation but note that there are a lot more out in the community. - -T> Note: This page only discusses using plugins, however if you are interested in writing your own please visit [Writing a Plugin](/development/how-to-write-a-plugin/). - - -## `plugins` - -`array` - -A list of webpack plugins. For example, [`DefinePlugin`](/plugins/define-plugin/) allows you to create global constants which can be configured at compile time. This can be useful for allowing different behavior between development builds and release builds. - -```js -module.exports = { - //... - plugins: [ - new webpack.DefinePlugin({ - // Definitions... - }) - ] -}; -``` - -A more complex example, using multiple plugins, might look something like this: - -```js -var webpack = require('webpack'); -// importing plugins that do not come by default in webpack -var ExtractTextPlugin = require('extract-text-webpack-plugin'); -var DashboardPlugin = require('webpack-dashboard/plugin'); - -// adding plugins to your configuration -module.exports = { - //... - plugins: [ - new ExtractTextPlugin({ - filename: 'build.min.css', - allChunks: true, - }), - new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), - // compile time plugins - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': '"production"', - }), - // webpack-dev-server enhancement plugins - new DashboardPlugin(), - new webpack.HotModuleReplacementPlugin(), - ] -}; -``` - - -# DevServer - -[webpack-dev-server](https://github.com/webpack/webpack-dev-server) can be used to quickly develop an application. See the [development guide](/guides/development/) to get started. - -This page describes the options that affect the behavior of webpack-dev-server (short: dev-server). - -T> Options that are compatible with [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) have 🔑 next to them. - - -## `devServer` - -`object` - -This set of options is picked up by [webpack-dev-server](https://github.com/webpack/webpack-dev-server) and can be used to change its behavior in various ways. Here's a simple example that gzips and serves everything from our `dist/` directory in the project root: - -__webpack.config.js__ - -```javascript -var path = require('path'); - -module.exports = { - //... - devServer: { - contentBase: path.join(__dirname, 'dist'), - compress: true, - port: 9000 - } -}; -``` - -When the server is started, there will be a message prior to the list of resolved modules: - -```bash -http://localhost:9000/ -webpack output is served from /build/ -Content not from webpack is served from /path/to/dist/ -``` - -that will give some background on where the server is located and what it's serving. - -If you're using dev-server through the Node.js API, the options in `devServer` will be ignored. Pass the options as a second parameter instead: `new WebpackDevServer(compiler, {...})`. [See here](https://github.com/webpack/webpack-dev-server/tree/master/examples/api/simple) for an example of how to use webpack-dev-server through the Node.js API. - -W> Be aware that when [exporting multiple configurations](/configuration/configuration-types/#exporting-multiple-configurations) only the `devServer` options for the first configuration will be taken into account and used for all the configurations in the array. - -T> If you're having trouble, navigating to the `/webpack-dev-server` route will show where files are served. For example, `http://localhost:9000/webpack-dev-server`. - -## `devServer.after` - -`function (app, server)` - -Provides the ability to execute custom middleware after all other middleware -internally within the server. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - after: function(app, server) { - // do fancy stuff - } - } -}; -``` - -## `devServer.allowedHosts` - -`array` - -This option allows you to whitelist services that are allowed to access the dev server. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - allowedHosts: [ - 'host.com', - 'subdomain.host.com', - 'subdomain2.host.com', - 'host2.com' - ] - } -}; -``` - -Mimicking django's `ALLOWED_HOSTS`, a value beginning with `.` can be used as a subdomain wildcard. `.host.com` will match `host.com`, `www.host.com`, and any other subdomain of `host.com`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - // this achieves the same effect as the first example - // with the bonus of not having to update your config - // if new subdomains need to access the dev server - allowedHosts: [ - '.host.com', - 'host2.com' - ] - } -}; -``` - -To use this option with the CLI pass the `--allowed-hosts` option a comma-delimited string. - -```bash -webpack-dev-server --entry /entry/file --output-path /output/path --allowed-hosts .host.com,host2.com -``` - -## `devServer.before` - -`function (app, server)` - -Provides the ability to execute custom middleware prior to all other middleware -internally within the server. This could be used to define custom handlers, for -example: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - before: function(app, server) { - app.get('/some/path', function(req, res) { - res.json({ custom: 'response' }); - }); - } - } -}; -``` - -## `devServer.bonjour` - -This option broadcasts the server via [ZeroConf](http://www.zeroconf.org/) networking on start - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - bonjour: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --bonjour -``` - - -## `devServer.clientLogLevel` - -`string: 'none' | 'info' | 'error' | 'warning'` - -When using _inline mode_, the console in your DevTools will show you messages e.g. before reloading, before an error or when [Hot Module Replacement](/concepts/hot-module-replacement/) is enabled. Defaults to `info`. - -`devServer.clientLogLevel` may be too verbose, you can turn logging off by setting it to `'none'`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - clientLogLevel: 'none' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --client-log-level none -``` - -## `devServer.color` - CLI only - -`boolean` - -Enables/Disables colors on the console. - -```bash -webpack-dev-server --color -``` - - -## `devServer.compress` - -`boolean` - -Enable [gzip compression](https://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/) for everything served: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - compress: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --compress -``` - - -## `devServer.contentBase` - -`boolean: false` `string` `[string]` `number` - -Tell the server where to serve content from. This is only necessary if you want to serve static files. [`devServer.publicPath`](#devserver-publicpath-) will be used to determine where the bundles should be served from, and takes precedence. - -T> It is recommended to use an absolute path. - -By default it will use your current working directory to serve content. To disable `contentBase` set it to `false`. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - contentBase: path.join(__dirname, 'public') - } -}; -``` - -It is also possible to serve from multiple directories: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - contentBase: [path.join(__dirname, 'public'), path.join(__dirname, 'assets')] - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --content-base /path/to/content/dir -``` - - -## `devServer.disableHostCheck` - -`boolean` - -When set to `true` this option bypasses host checking. __THIS IS NOT RECOMMENDED__ as apps that do not check the host are vulnerable to DNS rebinding attacks. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - disableHostCheck: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --disable-host-check -``` - - -## `devServer.filename` 🔑 - -`string` - -This option lets you reduce the compilations in [lazy mode](#devserver-lazy-). -By default in [lazy mode](#devserver-lazy-), every request results in a new compilation. With `filename`, it's possible to only compile when a certain file is requested. - -If [`output.filename`](/configuration/output/#output-filename) is set to `'bundle.js'` and `devServer.filename` is used like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - output: { - filename: 'bundle.js' - }, - devServer: { - lazy: true, - filename: 'bundle.js' - } -}; -``` - -It will now only compile the bundle when `/bundle.js` is requested. - -T> `filename` has no effect when used without [lazy mode](#devserver-lazy-). - - -## `devServer.headers` 🔑 - -`object` - -Adds headers to all responses: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - headers: { - 'X-Custom-Foo': 'bar' - } - } -}; -``` - - -## `devServer.historyApiFallback` - -`boolean` `object` - -When using the [HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/API/History), the `index.html` page will likely have to be served in place of any `404` responses. `devServer.historyApiFallback` is disabled by default. Enable it by passing: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: true - } -}; -``` - -By passing an object this behavior can be controlled further using options like `rewrites`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: { - rewrites: [ - { from: /^\/$/, to: '/views/landing.html' }, - { from: /^\/subpage/, to: '/views/subpage.html' }, - { from: /./, to: '/views/404.html' } - ] - } - } -}; -``` - -When using dots in your path (common with Angular), you may need to use the `disableDotRule`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - historyApiFallback: { - disableDotRule: true - } - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --history-api-fallback -``` - -For more options and information, see the [connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback) documentation. - - -## `devServer.host` - -`string` - -Specify a host to use. By default this is `localhost`. If you want your server to be accessible externally, specify it like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - host: '0.0.0.0' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --host 0.0.0.0 -``` - - -## `devServer.hot` - -`boolean` - -Enable webpack's [Hot Module Replacement](/concepts/hot-module-replacement/) feature: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - hot: true - } -}; -``` - -T> Note that [`webpack.HotModuleReplacementPlugin`](/plugins/hot-module-replacement-plugin/) is required to fully enable HMR. If `webpack` or `webpack-dev-server` are launched with the `--hot` option, this plugin will be added automatically, so you may not need to add this to your `webpack.config.js`. See the [HMR concepts page](/concepts/hot-module-replacement/) for more information. - - -## `devServer.hotOnly` - -`boolean` - -Enables Hot Module Replacement (see [`devServer.hot`](#devserver-hot)) without page refresh as fallback in case of build failures. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - hotOnly: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --hot-only -``` - - -## `devServer.https` - -`boolean` `object` - -By default dev-server will be served over HTTP. It can optionally be served over HTTP/2 with HTTPS: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - https: true - } -}; -``` - -With the above setting a self-signed certificate is used, but you can provide your own: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - https: { - key: fs.readFileSync('/path/to/server.key'), - cert: fs.readFileSync('/path/to/server.crt'), - ca: fs.readFileSync('/path/to/ca.pem'), - } - } -}; -``` - -This object is passed straight to Node.js HTTPS module, so see the [HTTPS documentation](https://nodejs.org/api/https.html) for more information. - -Usage via the CLI - -```bash -webpack-dev-server --https -``` - -To pass your own certificate via the CLI use the following options - -```bash -webpack-dev-server --https --key /path/to/server.key --cert /path/to/server.crt --cacert /path/to/ca.pem -``` - -## `devServer.index` - -`string` - -The filename that is considered the index file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - index: 'index.html' - } -}; -``` - - -## `devServer.info` - CLI only - -`boolean` - -Output cli information. It is enabled by default. - -```bash -webpack-dev-server --info=false -``` - - -## `devServer.inline` - -`boolean` - -Toggle between the dev-server's two different modes. By default the application will be served with _inline mode_ enabled. This means that a script will be inserted in your bundle to take care of live reloading, and build messages will appear in the browser console. - -It is also possible to use __iframe mode__, which uses an `<iframe>` under a notification bar with messages about the build. To switch to __iframe mode__: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - inline: false - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --inline=false -``` - -T> Inline mode is recommended for [Hot Module Replacement](/plugins/hot-module-replacement-plugin/) as it includes an HMR trigger from the websocket. Polling mode can be used as an alternative, but requires an additional entry point, `'webpack/hot/poll?1000'`. - - -## `devServer.lazy` 🔑 - -`boolean` - -When `devServer.lazy` is enabled, the dev-server will only compile the bundle when it gets requested. This means that webpack will not watch any file changes. We call this __lazy mode__. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - lazy: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --lazy -``` - -T> [`watchOptions`](#devserver-watchoptions-) will have no effect when used with __lazy mode__. - -T> If you use the CLI, make sure __inline mode__ is disabled. - - -## `devServer.noInfo` 🔑 - -`boolean` - -Tells dev-server to supress messages like the webpack bundle information. Errors and warnings will still be shown. `devServer.noInfo` is disabled by default. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - noInfo: true - } -}; -``` - - -## `devServer.open` - -`boolean` `string` - -Tells dev-server to open the browser after server had been started. Disabled by default. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - open: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --open -``` - -If no browser is provided (as shown above), your default browser will be used. To specify a different browser, just pass its name: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - open: 'Chrome' - } -}; -``` - -And via the CLI - -```bash -webpack-dev-server --open 'Chrome' -``` - -T> The browser application name is platform dependent. Don't hard code it in reusable modules. For example, `'Chrome'` is Google Chrome on macOS, `'google-chrome'` on Linux and `'chrome'` on Windows. - - -## `devServer.openPage` - -`string` - -Specify a page to navigate to when opening the browser. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - openPage: '/different/page' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --open-page "/different/page" -``` - - -## `devServer.overlay` - -`boolean` `object: { boolean errors, boolean warnings }` - -Shows a full-screen overlay in the browser when there are compiler errors or warnings. Disabled by default. If you want to show only compiler errors: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - overlay: true - } -}; -``` - -If you want to show warnings as well as errors: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - overlay: { - warnings: true, - errors: true - } - } -}; -``` - - -## `devServer.pfx` - -`string` - -When used via the CLI, a path to an SSL .pfx file. If used in options, it should be the bytestream of the .pfx file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - pfx: '/path/to/file.pfx' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --pfx /path/to/file.pfx -``` - - -## `devServer.pfxPassphrase` - -`string` - -The passphrase to a SSL PFX file. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - pfxPassphrase: 'passphrase' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --pfx-passphrase passphrase -``` - - -## `devServer.port` - -`number` - -Specify a port number to listen for requests on: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - port: 8080 - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --port 8080 -``` - - -## `devServer.proxy` - -`object` `[object, function]` - -Proxying some URLs can be useful when you have a separate API backend development server and you want to send API requests on the same domain. - -The dev-server makes use of the powerful [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) package. Check out its [documentation](https://github.com/chimurai/http-proxy-middleware#options) for more advanced usages. Note that some of `http-proxy-middleware`'s features do not require a `target` key, e.g. its `router` feature, but you will still need to include a `target` key in your config here, otherwise `webpack-dev-server` won't pass it along to `http-proxy-middleware`). - -With a backend on `localhost:3000`, you can use this to enable proxying: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': 'http://localhost:3000' - } - } -}; -``` - -A request to `/api/users` will now proxy the request to `http://localhost:3000/api/users`. - -If you don't want `/api` to be passed along, we need to rewrite the path: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'http://localhost:3000', - pathRewrite: {'^/api' : ''} - } - } - } -}; -``` - -A backend server running on HTTPS with an invalid certificate will not be accepted by default. If you want to, modify your config like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'https://other-server.example.com', - secure: false - } - } - } -}; -``` - -Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a function. - -In the function you get access to the request, response and proxy options. It must return either `false` or a path that will be served instead of continuing to proxy the request. - -E.g. for a browser request, you want to serve a HTML page, but for an API request you want to proxy it. You could do something like this: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': { - target: 'http://localhost:3000', - bypass: function(req, res, proxyOptions) { - if (req.headers.accept.indexOf('html') !== -1) { - console.log('Skipping proxy for browser request.'); - return '/index.html'; - } - } - } - } - } -}; -``` - -If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a `context` property: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: [{ - context: ['/auth', '/api'], - target: 'http://localhost:3000', - }] - } -}; -``` - -Note that requests to root won't be proxied by default. To enable root proxying, the `devServer.index` option should be specified as a falsy value: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - index: '', // specify to enable root proxying - host: '...', - contentBase: '...', - proxy: { - context: () => true, - target: 'http://localhost:1234' - } - } -}; -``` - -The origin of the host header is kept when proxying by default, you can set `changeOrigin` to `true` to override this behaviour. It is useful in some cases like using [name-based virtual hosted sites](https://en.wikipedia.org/wiki/Virtual_hosting#Name-based). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - proxy: { - '/api': 'http://localhost:3000', - changeOrigin: true - } - } -}; -``` - -## `devServer.progress` - CLI only - -`boolean` - -Output running progress to console. - -```bash -webpack-dev-server --progress -``` - - -## `devServer.public` - -`string` - -When using _inline mode_ and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on `window.location`, but if that fails you'll need to use this. - -For example, the dev-server is proxied by nginx, and available on `myapp.test`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - public: 'myapp.test:80' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --public myapp.test:80 -``` - - -## `devServer.publicPath` 🔑 - -`string` - -The bundled files will be available in the browser under this path. - -Imagine that the server is running under `http://localhost:8080` and [`output.filename`](/configuration/output/#output-filename) is set to `bundle.js`. By default the `devServer.publicPath` is `'/'`, so your bundle is available as `http://localhost:8080/bundle.js`. - -Change `devServer.publicPath` to put bundle under specific directory: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - publicPath: '/assets/' - } -}; -``` - -The bundle will now be available as `http://localhost:8080/assets/bundle.js`. - -T> Make sure `devServer.publicPath` always starts and ends with a forward slash. - -It is also possible to use a full URL. This is necessary for [Hot Module Replacement](/concepts/hot-module-replacement/). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - publicPath: 'http://localhost:8080/assets/' - } -}; -``` - -The bundle will also be available as `http://localhost:8080/assets/bundle.js`. - -T> It is recommended that `devServer.publicPath` is the same as [`output.publicPath`](/configuration/output/#output-publicpath). - - -## `devServer.quiet` 🔑 - -`boolean` - -With `devServer.quiet` enabled, nothing except the initial startup information will be written to the console. This also means that errors or warnings from webpack are not visible. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - quiet: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --quiet -``` - - -## `devServer.setup` - -`function (app, server)` - -W> This option is __deprecated__ in favor of [`devServer.before`](#devserver-before) and will be removed in v3.0.0. - -Here you can access the Express app object and add your own custom middleware to it. -For example, to define custom handlers for some paths: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - setup: function(app, server) { - app.get('/some/path', function(req, res) { - res.json({ custom: 'response' }); - }); - } - } -}; -``` - - -## `devServer.socket` - -`string` - -The Unix socket to listen to (instead of a host). - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - socket: 'socket' - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --socket socket -``` - - -## `devServer.staticOptions` - -It is possible to configure advanced options for serving static files from `contentBase`. See the [Express documentation](http://expressjs.com/en/4x/api.html#express.static) for the possible options. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - staticOptions: { - redirect: false - } - } -}; -``` - -T> This only works when using [`devServer.contentBase`](#devserver-contentbase) as a `string`. - - -## `devServer.stats` 🔑 - -`string: 'none' | 'errors-only' | 'minimal' | 'normal' | 'verbose'` `object` - -This option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you want some bundle information, but not all of it. - -To show only errors in your bundle: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - stats: 'errors-only' - } -}; -``` - -For more information, see the [__stats documentation__](/configuration/stats/). - -T> This option has no effect when used with `quiet` or `noInfo`. - - -## `devServer.stdin` - CLI only - -`boolean` - -This option closes the server when stdin ends. - -```bash -webpack-dev-server --stdin -``` - - -## `devServer.useLocalIp` - -`boolean` - -This option lets the browser open with your local IP. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - useLocalIp: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --useLocalIp -``` - - -## `devServer.watchContentBase` - -`boolean` - -Tell dev-server to watch the files served by the [`devServer.contentBase`](#devserver-contentbase) option. It is disabled by default. When enabled, file changes will trigger a full page reload. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - watchContentBase: true - } -}; -``` - -Usage via the CLI - -```bash -webpack-dev-server --watch-content-base -``` - - -## `devServer.watchOptions` 🔑 - -`object` - -Control options related to watching the files. - -webpack uses the file system to get notified of file changes. In some cases this does not work. For example, when using Network File System (NFS). [Vagrant](https://www.vagrantup.com/) also has a lot of problems with this. In these cases, use polling: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - devServer: { - watchOptions: { - poll: true - } - } -}; -``` - -If this is too heavy on the file system, you can change this to an integer to set the interval in milliseconds. - -See [WatchOptions](/configuration/watch/) for more options. - - -# Devtool - -This option controls if and how source maps are generated. - -Use the [`SourceMapDevToolPlugin`](/plugins/source-map-dev-tool-plugin) for a more fine grained configuration. See the [`source-map-loader`](/loaders/source-map-loader) to deal with existing source maps. - - -## `devtool` - -`string` `false` - -Choose a style of [source mapping](http://blog.teamtreehouse.com/introduction-source-maps) to enhance the debugging process. These values can affect build and rebuild speed dramatically. - -T> The webpack repository contains an [example showing the effect of all `devtool` variants](https://github.com/webpack/webpack/tree/master/examples/source-map). Those examples will likely help you to understand the differences. - -T> Instead of using the `devtool` option you can also use `SourceMapDevToolPlugin`/`EvalSourceMapDevToolPlugin` directly as it has more options. Never use both the `devtool` option and plugin together. The `devtool` option adds the plugin internally so you would end up with the plugin applied twice. - -devtool | build | rebuild | production | quality ------------------------------- | ----- | ------- | ---------- | ----------------------------- -(none) | +++ | +++ | yes | bundled code -eval | +++ | +++ | no | generated code -cheap-eval-source-map | + | ++ | no | transformed code (lines only) -cheap-module-eval-source-map | o | ++ | no | original source (lines only) -eval-source-map | -- | + | no | original source -cheap-source-map | + | o | yes | transformed code (lines only) -cheap-module-source-map | o | - | yes | original source (lines only) -inline-cheap-source-map | + | o | no | transformed code (lines only) -inline-cheap-module-source-map | o | - | no | original source (lines only) -source-map | -- | -- | yes | original source -inline-source-map | -- | -- | no | original source -hidden-source-map | -- | -- | yes | original source -nosources-source-map | -- | -- | yes | without source content - -T> `+++` super fast, `++` fast, `+` pretty fast, `o` medium, `-` pretty slow, `--` slow - -Some of these values are suited for development and some for production. For development you typically want fast Source Maps at the cost of bundle size, but for production you want separate Source Maps that are accurate and support minimizing. - -W> There are some issues with Source Maps in Chrome. [We need your help!](https://github.com/webpack/webpack/issues/3165). - -T> See [`output.sourceMapFilename`](/configuration/output#output-sourcemapfilename) to customize the filenames of generated Source Maps. - - -### Qualities - -`bundled code` - You see all generated code as a big blob of code. You don't see modules separated from each other. - -`generated code` - You see each module separated from each other, annotated with module names. You see the code generated by webpack. Example: Instead of `import {test} from "module"; test();` you see something like `var module__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); module__WEBPACK_IMPORTED_MODULE_1__.a();`. - -`transformed code` - You see each module separated from each other, annotated with module names. You see the code before webpack transforms it, but after Loaders transpile it. Example: Instead of `import {test} from "module"; class A extends test {}` you see something like `import {test} from "module"; var A = function(_test) { ... }(test);` - -`original source` - You see each module separated from each other, annotated with module names. You see the code before transpilation, as you authored it. This depends on Loader support. - -`without source content` - Contents for the sources are not included in the Source Maps. Browsers usually try to load the source from the webserver or filesystem. You have to make sure to set [`output.devtoolModuleFilenameTemplate`](/configuration/output/#output-devtoolmodulefilenametemplate) correctly to match source urls. - -`(lines only)` - Source Maps are simplified to a single mapping per line. This usually means a single mapping per statement (assuming you author is this way). This prevents you from debugging execution on statement level and from settings breakpoints on columns of a line. Combining with minimizing is not possible as minimizers usually only emit a single line. - - -### Development - -The following options are ideal for development: - -`eval` - Each module is executed with `eval()` and `//@ sourceURL`. This is pretty fast. The main disadvantage is that it doesn't display line numbers correctly since it gets mapped to transpiled code instead of the original code (No Source Maps from Loaders). - -`eval-source-map` - Each module is executed with `eval()` and a SourceMap is added as a DataUrl to the `eval()`. Initially it is slow, but it provides fast rebuild speed and yields real files. Line numbers are correctly mapped since it gets mapped to the original code. It yields the best quality SourceMaps for development. - -`cheap-eval-source-map` - Similar to `eval-source-map`, each module is executed with `eval()`. It is "cheap" because it doesn't have column mappings, it only maps line numbers. It ignores SourceMaps from Loaders and only display transpiled code similar to the `eval` devtool. - -`cheap-module-eval-source-map` - Similar to `cheap-eval-source-map`, however, in this case Source Maps from Loaders are processed for better results. However Loader Source Maps are simplified to a single mapping per line. - -### Special cases - -The following options are not ideal for development nor production. They are needed for some special cases, i. e. for some 3rd party tools. - -`inline-source-map` - A SourceMap is added as a DataUrl to the bundle. - -`cheap-source-map` - A SourceMap without column-mappings ignoring loader Source Maps. - -`inline-cheap-source-map` - Similar to `cheap-source-map` but SourceMap is added as a DataUrl to the bundle. - -`cheap-module-source-map` - A SourceMap without column-mappings that simplifies loader Source Maps to a single mapping per line. - -`inline-cheap-module-source-map` - Similar to `cheap-module-source-map` but SourceMap is added as a DataUrl to the bundle. - - -### Production - -These options are typically used in production: - -`(none)` (Omit the `devtool` option) - No SourceMap is emitted. This is a good option to start with. - -`source-map` - A full SourceMap is emitted as a separate file. It adds a reference comment to the bundle so development tools know where to find it. - -W> You should configure your server to disallow access to the Source Map file for normal users! - -`hidden-source-map` - Same as `source-map`, but doesn't add a reference comment to the bundle. Useful if you only want SourceMaps to map error stack traces from error reports, but don't want to expose your SourceMap for the browser development tools. - -W> You should not deploy the Source Map file to the webserver. Instead only use it for error report tooling. - -`nosources-source-map` - A SourceMap is created without the `sourcesContent` in it. It can be used to map stack traces on the client without exposing all of the source code. You can deploy the Source Map file to the webserver. - -W> It still exposes filenames and structure for decompiling, but it doesn't expose the original code. - -T> When using the `terser-webpack-plugin` you must provide the `sourceMap: true` option to enable SourceMap support. - - -# Target - -webpack can compile for multiple environments or _targets_. To understand what a `target` is in detail, read through [the targets concept page](/concepts/targets/). - -## `target` - -`string | function (compiler)` - -Instructs webpack to target a specific environment. - - -### `string` - -The following string values are supported via [`WebpackOptionsApply`](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js): - -Option | Description ---------------------- | ----------------------- -`async-node` | Compile for usage in a Node.js-like environment (uses `fs` and `vm` to load chunks asynchronously) -`electron-main` | Compile for [Electron](https://electronjs.org/) for main process. -`electron-renderer` | Compile for [Electron](https://electronjs.org/) for renderer process, providing a target using `JsonpTemplatePlugin`, `FunctionModulePlugin` for browser environments and `NodeTargetPlugin` and `ExternalsPlugin` for CommonJS and Electron built-in modules. -`node` | Compile for usage in a Node.js-like environment (uses Node.js `require` to load chunks) -`node-webkit` | Compile for usage in WebKit and uses JSONP for chunk loading. Allows importing of built-in Node.js modules and [`nw.gui`](http://docs.nwjs.io/en/latest/) (experimental) -`web` | Compile for usage in a browser-like environment __(default)__ -`webworker` | Compile as WebWorker - -For example, when the `target` is set to `"electron-main"`, webpack includes multiple electron specific variables. For more information on which templates and externals are used, you can refer to webpack's [source code](https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js#L148-L183). - - -### `function` - -If a function is passed, then it will be called with the compiler as a parameter. Set it to a function if none of the predefined targets from the list above meet your needs. - -For example, if you don't want any of the plugins they applied: - -```js -const options = { - target: () => undefined -}; -``` - -Or you can apply specific plugins you want: - -```js -const webpack = require('webpack'); - -const options = { - target: (compiler) => { - compiler.apply( - new webpack.JsonpTemplatePlugin(options.output), - new webpack.LoaderTargetPlugin('web') - ); - } -}; -``` - - -# Watch and WatchOptions - -webpack can watch files and recompile whenever they change. This page explains how to enable this and a couple of tweaks you can make if watching does not work properly for you. - - -## `watch` - -`boolean` - -Turn on watch mode. This means that after the initial build, webpack will continue to watch for changes in any of the resolved files. Watch mode is turned off by default: - -```js -module.exports = { - //... - watch: false -}; -``` - -T> In webpack-dev-server and webpack-dev-middleware watch mode is enabled by default. - - -## `watchOptions` - -`object` - -A set of options used to customize watch mode: - -```js -module.exports = { - //... - watchOptions: { - aggregateTimeout: 300, - poll: 1000 - } -}; -``` - - -## `watchOptions.aggregateTimeout` - -`number` - -Add a delay before rebuilding once the first file changed. This allows webpack to aggregate any other changes made during this time period into one rebuild. Pass a value in milliseconds: - -```js -module.exports = { - //... - watchOptions: { - aggregateTimeout: 300 // The default - } -}; -``` - - -## `watchOptions.ignored` - -For some systems, watching many file systems can result in a lot of CPU or memory usage. It is possible to exclude a huge folder like `node_modules`: - -```js -module.exports = { - //... - watchOptions: { - ignored: /node_modules/ - } -}; -``` - -It is also possible to have and use multiple [anymatch](https://github.com/micromatch/anymatch) patterns: - -```js -module.exports = { - //... - watchOptions: { - ignored: ['files/**/*.js', 'node_modules'] - } -}; -``` - -T> If you use `require.context`, webpack will watch your entire directory. You will need to ignore files and/or directories so that unwanted changes will not trigger a rebuild. - - -## `watchOptions.poll` - -`boolean` `number` - -Turn on [polling](https://whatis.techtarget.com/definition/polling) by passing `true`, or specifying a poll interval in milliseconds: - -```js -module.exports = { - //... - watchOptions: { - poll: 1000 // Check for changes every second - } -}; -``` - -T> If watching does not work for you, try out this option. Watching does not work with NFS and machines in VirtualBox. - - -## `info-verbosity` - -`string`: `none` `info` `verbose` - -Controls verbosity of the lifecycle messaging, e.g. the `Started watching files...` log. Setting `info-verbosity` to `verbose` will also message to console at the beginning and the end of incremental build. `info-verbosity` is set to `info` by default. - -```bash -webpack --watch --info-verbosity verbose -``` - - -## Troubleshooting - -If you are experiencing any issues, please see the following notes. There are a variety of reasons why webpack might miss a file change. - -### Changes Seen But Not Processed - -Verify that webpack is not being notified of changes by running webpack with the --progress flag. If progress shows on save but no files are outputted, it is likely a configuration issue, not a file watching issue. - -```bash -webpack --watch --progress -``` - -### Not Enough Watchers - -Verify that you have enough available watchers in your system. If this value is too low, the file watcher in Webpack won't recognize the changes: - -```bash -cat /proc/sys/fs/inotify/max_user_watches -``` - -Arch users, add `fs.inotify.max_user_watches=524288` to `/etc/sysctl.d/99-sysctl.conf` and then execute `sysctl --system`. Ubuntu users (and possibly others), execute: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`. - -### macOS fsevents Bug - -On macOS, folders can get corrupted in certain scenarios. See [this article](https://github.com/livereload/livereload-site/blob/master/livereload.com/_articles/troubleshooting/os-x-fsevents-bug-may-prevent-monitoring-of-certain-folders.md). - -### Windows Paths - -Because webpack expects absolute paths for many config options such as `__dirname + "/app/folder"` the Windows `\` path separator can break some functionality. - -Use the correct separators. I.e. `path.resolve(__dirname, "app/folder")` or `path.join(__dirname, "app", "folder")`. - -### Vim - -On some machines Vim is preconfigured with the [backupcopy option](http://vimdoc.sourceforge.net/htmldoc/options.html#'backupcopy') set to `auto`. This could potentially cause problems with the system's file watching mechanism. Switching this option to `yes` will make sure a copy of the file is made and the original one overwritten on save. - -`:set backupcopy=yes` - -### Saving in WebStorm - -When using the JetBrains WebStorm IDE, you may find that saving changed files does not trigger the watcher as you might expect. Try disabling the `safe write` option in the settings, which determines whether files are saved to a temporary location first before the originals are overwritten: uncheck `File > Settings... > System Settings > Use "safe write" (save changes to a temporary file first)`. - - -# Externals - -The `externals` configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment. This feature is typically most useful to __library developers__, however there are a variety of applications for it. - -T> __consumer__ here is any end user application that includes the library that you have bundled using webpack. - - -## `externals` - -`string` `object` `function` `regex` - -__Prevent bundling__ of certain `import`ed packages and instead retrieve these _external dependencies_ at runtime. - -For example, to include [jQuery](https://jquery.com/) from a CDN instead of bundling it: - -__index.html__ - -``` html -<script - src="https://code.jquery.com/jquery-3.1.0.js" - integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" - crossorigin="anonymous"> -</script> -``` - -__webpack.config.js__ - -```javascript -module.exports = { - //... - externals: { - jquery: 'jQuery' - } -}; -``` - -This leaves any dependent modules unchanged, i.e. the code shown below will still work: - -```javascript -import $ from 'jquery'; - -$('.my-element').animate(/* ... */); -``` - -The bundle with external dependencies can be used in various module contexts, such as [CommonJS, AMD, global and ES2015 modules](/concepts/modules). The external library may be available in any of these forms: - -- __root__: The library should be available as a global variable (e.g. via a script tag). -- __commonjs__: The library should be available as a CommonJS module. -- __commonjs2__: Similar to the above but where the export is `module.exports.default`. -- __amd__: Similar to `commonjs` but using AMD module system. - -The following syntaxes are accepted... - - -### string - -See the example above. The property name `jquery` indicates that the module `jquery` in `import $ from 'jquery'` should be excluded. In order to replace this module, the value `jQuery` will be used to retrieve a global `jQuery` variable. In other words, when a string is provided it will be treated as `root` (defined above and below). - - -### array - -```javascript -module.exports = { - //... - externals: { - subtract: ['./math', 'subtract'] - } -}; -``` - -`subtract: ['./math', 'subtract']` converts to a parent child construct, where `./math` is the parent module and your bundle only requires the subset under `subtract` variable. - - -### object - -W> An object with `{ root, amd, commonjs, ... }` is only allowed for [`libraryTarget: 'umd'`](/configuration/output/#output-librarytarget). It's not allowed for other library targets. - -```javascript -module.exports = { - //... - externals : { - react: 'react' - }, - - // or - - externals : { - lodash : { - commonjs: 'lodash', - amd: 'lodash', - root: '_' // indicates global variable - } - }, - - // or - - externals : { - subtract : { - root: ['math', 'subtract'] - } - } -}; -``` - -This syntax is used to describe all the possible ways that an external library can be available. `lodash` here is available as `lodash` under AMD and CommonJS module systems but available as `_` in a global variable form. `subtract` here is available via the property `subtract` under the global `math` object (e.g. `window['math']['subtract']`). - - -### function - -It might be useful to define your own function to control the behavior of what you want to externalize from webpack. [webpack-node-externals](https://www.npmjs.com/package/webpack-node-externals), for example, excludes all modules from the `node_modules` directory and provides some options to, for example, whitelist packages. - -It basically comes down to this: - -```javascript -module.exports = { - //... - externals: [ - function(context, request, callback) { - if (/^yourregex$/.test(request)){ - return callback(null, 'commonjs ' + request); - } - callback(); - } - ] -}; -``` - -The `'commonjs ' + request` defines the type of module that needs to be externalized. - - -### regex - -Every dependency that matches the given regular expression will be excluded from the output bundles. - -```javascript -module.exports = { - //... - externals: /^(jquery|\$)$/i -}; -``` - -In this case any dependency named `jQuery`, capitalized or not, or `$` would be externalized. - -### Combining syntaxes - -Sometimes you may want to use a combination of the above syntaxes. This can be done in the following manner: - -```javascript -module.exports = { - //... - externals: [ - { - // String - react: 'react', - // Object - lodash : { - commonjs: 'lodash', - amd: 'lodash', - root: '_' // indicates global variable - }, - // Array - subtract: ['./math', 'subtract'] - }, - // Function - function(context, request, callback) { - if (/^yourregex$/.test(request)){ - return callback(null, 'commonjs ' + request); - } - callback(); - }, - // Regex - /^(jquery|\$)$/i - ] -}; -``` - -For more information on how to use this configuration, please refer to the article on [how to author a library](/guides/author-libraries). - - -# Node - -These options configure whether to polyfill or mock certain [Node.js globals](https://nodejs.org/docs/latest/api/globals.html) and modules. This allows code originally written for the Node.js environment to run in other environments like the browser. - -This feature is provided by webpack's internal [`NodeStuffPlugin`](https://github.com/webpack/webpack/blob/master/lib/NodeStuffPlugin.js) plugin. If the target is "web" (default) or "webworker", the [`NodeSourcePlugin`](https://github.com/webpack/webpack/blob/master/lib/node/NodeSourcePlugin.js) plugin is also activated. - - -## `node` - -`object` - -This is an object where each property is the name of a Node global or module and each value may be one of the following... - -- `true`: Provide a polyfill. -- `"mock"`: Provide a mock that implements the expected interface but has little or no functionality. -- `"empty"`: Provide an empty object. -- `false`: Provide nothing. Code that expects this object may crash with a `ReferenceError`. Code that attempts to import the module using `require('modulename')` may trigger a `Cannot find module "modulename"` error. - -W> Not every Node global supports all four options. The compiler will throw an error for property-value combinations that aren't supported (e.g. `process: 'empty'`). See the sections below for more details. - -These are the defaults: - -```js -module.exports = { - //... - node: { - console: false, - global: true, - process: true, - __filename: 'mock', - __dirname: 'mock', - Buffer: true, - setImmediate: true - - // See "Other node core libraries" for additional options. - } -}; -``` - -Since webpack 3.0.0, the `node` option may be set to `false` to completely turn off the `NodeStuffPlugin` and `NodeSourcePlugin` plugins. - - -## `node.console` - -`boolean | "mock"` - -Default: `false` - -The browser provides a `console` object with a very similar interface to the Node.js `console`, so a polyfill is generally not needed. - - -## `node.process` - -`boolean | "mock"` - -Default: `true` - - -## `node.global` - -`boolean` - -Default: `true` - -See [the source](https://github.com/webpack/webpack/blob/master/buildin/global.js) for the exact behavior of this object. - - -## `node.__filename` - -`boolean | "mock"` - -Default: `"mock"` - -Options: - -- `true`: The filename of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). -- `false`: The regular Node.js `__filename` behavior. The filename of the __output__ file when run in a Node.js environment. -- `"mock"`: The fixed value `"index.js"`. - - -## `node.__dirname` - -`boolean | "mock"` - -Default: `"mock"` - -Options: - -- `true`: The dirname of the __input__ file relative to the [`context` option](https://webpack.js.org/configuration/entry-context/#context). -- `false`: The regular Node.js `__dirname` behavior. The dirname of the __output__ file when run in a Node.js environment. -- `"mock"`: The fixed value `"/"`. - - -## `node.Buffer` - -`boolean | "mock"` - -Default: `true` - - -## `node.setImmediate` - -`boolean | "mock" | "empty"` - -Default: `true` - - -## Other node core libraries - -`boolean | "mock" | "empty"` - -W> This option is only activated (via `NodeSourcePlugin`) when the target is unspecified, "web" or "webworker". - -Polyfills for Node.js core libraries from [`node-libs-browser`](https://github.com/webpack/node-libs-browser) are used if available, when the `NodeSourcePlugin` plugin is enabled. See the list of [Node.js core libraries and their polyfills](https://github.com/webpack/node-libs-browser#readme). - -By default, webpack will polyfill each library if there is a known polyfill or do nothing if there is not one. In the latter case, webpack will behave as if the module name was configured with the `false` value. - -T> To import a built-in module, use [`__non_webpack_require__`](/api/module-variables/#__non_webpack_require__-webpack-specific-), i.e. `__non_webpack_require__('modulename')` instead of `require('modulename')`. - -Example: - -```js -module.exports = { - //... - node: { - dns: 'mock', - fs: 'empty', - path: true, - url: false - } -}; -``` - - -# Performance - -These options allows you to control how webpack notifies you of assets and entry points that exceed a specific file limit. -This feature was inspired by the idea of [webpack Performance Budgets](https://github.com/webpack/webpack/issues/3216). - -## `performance` - -`object` - -Configure how performance hints are shown. For example if you have an asset that is over 250kb, webpack will emit a warning notifying you of this. - - -## `performance.hints` - -`false | "error" | "warning"` - -Turns hints on/off. In addition, tells webpack to throw either an error or a warning when hints are found. This property is set to `"warning"` by default. - -Given an asset is created that is over 250kb: - -```js -module.exports = { - //... - performance: { - hints: false - } -}; -``` - -No hint warnings or errors are shown. - -```js -module.exports = { - //... - performance: { - hints: 'warning' - } -}; -``` - -A warning will be displayed notifying you of a large asset. We recommend something like this for development environments. - -```js -module.exports = { - //... - performance: { - hints: 'error' - } -}; -``` - -An error will be displayed notifying you of a large asset. We recommend using `hints: "error"` during production builds to help prevent deploying production bundles that are too large, impacting webpage performance. - -## `performance.maxEntrypointSize` - -`int` - -An entry point represents all assets that would be utilized during initial load time for a specific entry. This option controls when webpack should emit performance hints based on the maximum entry point size. The default value is `250000` (bytes). - -```js -module.exports = { - //... - performance: { - maxEntrypointSize: 400000 - } -}; -``` - -## `performance.maxAssetSize` - -`int` - -An asset is any emitted file from webpack. This option controls when webpack emits a performance hint based on individual asset size. The default value is `250000` (bytes). - - -```js -module.exports = { - //... - performance: { - maxAssetSize: 100000 - } -}; -``` - -## `performance.assetFilter` - -`Function` - -This property allows webpack to control what files are used to calculate performance hints. The default function is seen below: - -```js -function assetFilter(assetFilename) { - return !(/\.map$/.test(assetFilename)); -} -``` - -You can override this property by passing your own function in: - -```js -module.exports = { - //... - performance: { - assetFilter: function(assetFilename) { - return assetFilename.endsWith('.js'); - } - } -}; -``` - -The example above will only give you performance hints based on `.js` files. - - -# Stats - -The `stats` option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you don't want to use `quiet` or `noInfo` because you want some bundle information, but not all of it. - -T> For webpack-dev-server, this property needs to be in the `devServer` object. - -W> This option does not have any effect when using the Node.js API. - -## `stats` - -`object` `string` - -There are some presets available to use as a shortcut. Use them like this: - -```js -module.exports = { - //... - stats: 'errors-only' -}; -``` - -| Preset | Alternative | Description | -|--------|-------------|-------------| -| `"errors-only"` | _none_ | Only output when errors happen | -| `"minimal"` | _none_ | Only output when errors or new compilation happen | -| `"none"` | `false` | Output nothing | -| `"normal"` | `true` | Standard output | -| `"verbose"` | _none_ | Output everything | - -For more granular control, it is possible to specify exactly what information you want. Please note that all of the options in this object are optional. - -<!-- eslint-skip --> - -```js -module.exports = { - //... - stats: { - // fallback value for stats options when an option is not defined (has precedence over local webpack defaults) - all: undefined, - - // Add asset Information - assets: true, - - // Sort assets by a field - // You can reverse the sort with `!field`. - // Some possible values: 'id' (default), 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - assetsSort: "field", - - // Add build date and time information - builtAt: true, - - // Add information about cached (not built) modules - cached: true, - - // Show cached assets (setting this to `false` only shows emitted files) - cachedAssets: true, - - // Add children information - children: true, - - // Add chunk information (setting this to `false` allows for a less verbose output) - chunks: true, - - // Add namedChunkGroups information - chunkGroups: true, - - // Add built modules information to chunk information - chunkModules: true, - - // Add the origins of chunks and chunk merging info - chunkOrigins: true, - - // Sort the chunks by a field - // You can reverse the sort with `!field`. Default is `id`. - // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - chunksSort: "field", - - // Context directory for request shortening - context: "../src/", - - // `webpack --colors` equivalent - colors: false, - - // Display the distance from the entry point for each module - depth: false, - - // Display the entry points with the corresponding bundles - entrypoints: false, - - // Add --env information - env: false, - - // Add errors - errors: true, - - // Add details to errors (like resolving log) - errorDetails: true, - - // Exclude assets from being displayed in stats - // This can be done with a String, a RegExp, a Function getting the assets name - // and returning a boolean or an Array of the above. - excludeAssets: "filter" | /filter/ | (assetName) => true | false | - ["filter"] | [/filter/] | [(assetName) => true|false], - - // Exclude modules from being displayed in stats - // This can be done with a String, a RegExp, a Function getting the modules source - // and returning a boolean or an Array of the above. - excludeModules: "filter" | /filter/ | (moduleSource) => true | false | - ["filter"] | [/filter/] | [(moduleSource) => true|false], - - // See excludeModules - exclude: "filter" | /filter/ | (moduleSource) => true | false | - ["filter"] | [/filter/] | [(moduleSource) => true|false], - - // Add the hash of the compilation - hash: true, - - // Set the maximum number of modules to be shown - maxModules: 15, - - // Add built modules information - modules: true, - - // Sort the modules by a field - // You can reverse the sort with `!field`. Default is `id`. - // Some other possible values: 'name', 'size', 'chunks', 'failed', 'issuer' - // For a complete list of fields see the bottom of the page - modulesSort: "field", - - // Show dependencies and origin of warnings/errors (since webpack 2.5.0) - moduleTrace: true, - - // Show performance hint when file size exceeds `performance.maxAssetSize` - performance: true, - - // Show the exports of the modules - providedExports: false, - - // Add public path information - publicPath: true, - - // Add information about the reasons why modules are included - reasons: true, - - // Add the source code of modules - source: false, - - // Add timing information - timings: true, - - // Show which exports of a module are used - usedExports: false, - - // Add webpack version information - version: true, - - // Add warnings - warnings: true, - - // Filter warnings to be shown (since webpack 2.4.0), - // can be a String, Regexp, a function getting the warning and returning a boolean - // or an Array of a combination of the above. First match wins. - warningsFilter: "filter" | /filter/ | ["filter", /filter/] | (warning) => true|false - } -} -``` - -If you want to use one of the pre-defined behaviours e.g. `'minimal'` but still override one or more of the rules, see [the source code](https://github.com/webpack/webpack/blob/master/lib/Stats.js#L1394-L1401). You would want to copy the configuration options from `case 'minimal': ...` and add your additional rules while providing an object to `stats`. - -__webpack.config.js__ - -```javascript -module.exports = { - //.. - stats: { - // copied from `'minimal'` - all: false, - modules: true, - maxModules: 0, - errors: true, - warnings: true, - // our additional options - moduleTrace: true, - errorDetails: true - } -}; -``` - -### Sorting fields - -For `assetsSort`, `chunksSort` and `moduleSort` there are several possible fields that you can sort items by: - -- `id` is the item's id; -- `name` - a item's name that was assigned to it upon importing; -- `size` - a size of item in bytes; -- `chunks` - what chunks the item originates from (for example, if there are multiple subchunks for one chunk - the subchunks will be grouped together according to their main chunk); -- `errors` - amount of errors in items; -- `warnings` - amount of warnings in items; -- `failed` - whether the item has failed compilation; -- `cacheable` - whether the item is cacheable; -- `built` - whether the asset has been built; -- `prefetched` - whether the asset will be prefetched; -- `optional` - whether the asset is optional; -- `identifier` - identifier of the item; -- `index` - item's processing index; -- `index2` -- `profile` -- `issuer` - an identifier of the issuer; -- `issuerId` - an id of the issuer; -- `issuerName` - a name of the issuer; -- `issuerPath` - a full issuer object. There's no real need to sort by this field; - - -# Other Options - - -These are the remaining configuration options supported by webpack. - -W> Help Wanted: This page is still a work in progress. If you are familiar with any of the options for which the description or examples are incomplete, please create an issue and submit a PR at the [docs repo](https://github.com/webpack/webpack.js.org)! - - -## `amd` - -`object` - -Set the value of `require.amd` or `define.amd`: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - amd: { - jQuery: true - } -}; -``` - -Certain popular modules written for AMD, most notably jQuery versions 1.7.0 to 1.9.1, will only register as an AMD module if the loader indicates it has taken [special allowances](https://github.com/amdjs/amdjs-api/wiki/jQuery-and-AMD) for multiple versions being included on a page. - -The allowances were the ability to restrict registrations to a specific version or to support different sandboxes with different defined modules. - -This option allows you to set the key your module looks for to a truthy value. -As it happens, the AMD support in webpack ignores the defined name anyways. - - -## `bail` - -`boolean` - -Fail out on the first error instead of tolerating it. By default webpack will log these errors in red in the terminal, as well as the browser console when using HMR, but continue bundling. To enable it: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - bail: true -}; -``` - -This will force webpack to exit its bundling process. - - -## `cache` - -`boolean` `object` - -Cache the generated webpack modules and chunks to improve build speed. Caching is enabled by default while in watch mode. To disable caching simply pass: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - cache: false -}; -``` - -If an object is passed, webpack will use this object for caching. Keeping a reference to this object will allow one to share the same cache between compiler calls: - -__webpack.config.js__ - -```javascript -let SharedCache = {}; - -module.exports = { - //... - cache: SharedCache -}; -``` - -W> Don't share the cache between calls with different options. - -?> Elaborate on the warning and example - calls with different configuration options? - - -## `loader` - -`object` - -Expose custom values into the loader context. - -?> Add an example... - - -## `parallelism` - -`number` - -Limit the number of parallel processed modules. Can be used to fine tune performance or to get more reliable profiling results. - - -## `profile` - -`boolean` - -Capture a "profile" of the application, including statistics and hints, which can then be dissected using the [Analyze](https://webpack.github.io/analyse/) tool. - -T> Use the [StatsPlugin](https://www.npmjs.com/package/stats-webpack-plugin) for more control over the generated profile. - -T> Combine with `parallelism: 1` for better results. - - -## `recordsPath` - -`string` - -Use this option to generate a JSON file containing webpack "records" -- pieces of data used to store module identifiers across multiple builds. You can use this file to track how modules change between builds. To generate one, simply specify a location: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - recordsPath: path.join(__dirname, 'records.json') -}; -``` - -Records are particularly useful if you have a complex setup that leverages [Code Splitting](/guides/code-splitting). The data can be used to ensure the split bundles are achieving the [caching](/guides/caching) behavior you need. - -T> Note that although this file is generated by the compiler, you may still want to track it in source control to keep a history of how it has changed over time. - -W> Setting `recordsPath` will essentially set `recordsInputPath` and `recordsOutputPath` to the same location. This is usually all that's necessary unless you decide to change the name of the file containing the records. See below for an example. - - -## `recordsInputPath` - -`string` - -Specify the file from which to read the last set of records. This can be used to rename a records file. See the example below. - - -## `recordsOutputPath` - -`string` - -Specify where the records should be written. The following example shows how you might use this option in combination with `recordsInputPath` to rename a records file: - -__webpack.config.js__ - -```javascript -module.exports = { - //... - recordsInputPath: path.join(__dirname, 'records.json'), - recordsOutputPath: path.join(__dirname, 'newRecords.json') -}; -``` - - -## `name` - -`string` - -Name of the configuration. Used when loading multiple configurations. - -__webpack.config.js__ - -```javascript -module.exports = { - //... - name: 'admin-app' -}; -``` diff --git a/src/content/contribute/_contribute_all.md b/src/content/contribute/_contribute_all.md deleted file mode 100644 index beab316a12a7..000000000000 --- a/src/content/contribute/_contribute_all.md +++ /dev/null @@ -1,979 +0,0 @@ - - -# Contribute - -The people who contribute to webpack do so for the love of open source, our users and ecosystem, and most importantly, pushing the web forward together. Because of our [Open Collective](https://opencollective.com/webpack) model for funding and transparency, we are able to funnel support and funds through contributors, dependent projects, and the contributor and core teams. To make a donation, simply click the button below... - -<div align="center"> - <a href="https://opencollective.com/webpack/donate" target="_blank"> - <img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" width=300 /> - </a> -</div> - -But what is the return on the investment? - - -## Developers - -The biggest core feature we'd like to provide is enjoyable development experience. Developers like you can help by contributing to rich and vibrant documentation, issuing pull requests to help us cover niche use cases, and to help sustain what you love about webpack. - -### How Can I Help? - -Anybody can help by doing any of the following: - -- Ask your employer to use webpack in projects. -- Help us write and maintain the content on this site (see the [writer's guide](/writers-guide)). -- Contribute to the [core repository](https://github.com/webpack/webpack). -- Become a backer or sponsor on [open collective](https://opencollective.com/webpack#support). - -### Encouraging Employers - -You can ask your employer to improve your workflow by leveraging webpack: an all-in-one tool for fonts, images and image optimization, and json. Explain to them how webpack will attempt to bundle your code and assets the best it can for the smallest file size, leading to speedier sites and applications. - -### Your Contributions - -Contributing to webpack is not contributing to an exclusive club. You as a developer are contributing to the overall health of downstream projects. Hundreds, if not thousands, of projects depend on webpack and contributing will make the ecosystem better for all users. - -The remainder of this section of the site is dedicated to developers such as yourself who would like to become a part of our ever-growing community: - -- [Writing a Loader](./writing-a-loader) -- [Writing a Plugin](./writing-a-plugin) -- [Plugin Patterns](./plugin-patterns) -- [Release Process](./release-process) - - -## Executives - -CTO's, VPs, and owners can help too! - -<!-- add slides here regarding monetary value/dev time/tooling --> - -webpack is an all-in-one tool for bundling your code. It can handle fonts, images, data and more with the help of community-driven plugins and loaders. Having all of your assets be handled by one tool is immensely helpful, as you or your team can spend less time making sure a machine with many moving parts is working correctly and more time building your product. - -### Sponsorship - -Aside from monetary assistance, companies can support webpack by: - -- Providing developers that are not actively working on a project. -- Contributing computing power for improved CI and regression testing. - -You can also encourage your developers to contribute to the ecosystem by open-sourcing webpack loaders, plugins and other utilities. And, as mentioned above, we would greatly appreciate any help increasing our CI/CD infrastructure. - -### Anyone Else - -To anyone else who is interested in helping our mission -- e.g. venture capitalists, government entities, digital agencies, etc. -- we would love for you to work with us, one of the top npm packages, to improve your product! Please don't hesitate to reach out with questions. - -<!-- add slides here --> - - -# Writer's Guide - -The following sections contain all you need to know about editing and formatting the content within this site. Make sure to do some research before starting your edits or additions. Sometimes the toughest part is finding where the content should live and determining whether or not it already exists. - - -## Process - -1. Check related issue if an article links to one. -2. Hit `edit` and expand on the structure. -3. PR changes. - - -## YAML Frontmatter - -Each article contains a small section at the top written in [YAML Frontmatter](https://jekyllrb.com/docs/frontmatter/): - -``` yaml ---- -title: My Article -group: My Sub-Section -sort: 3 -contributors: - - [github username] -related: - - title: Title of Related Article - url: [url of related article] ---- -``` - -Let's break these down: - -- `title`: The name of the article. -- `group`: The name of the sub-section -- `sort`: The order of the article within its section (or) sub-section if it is present. -- `contributors`: A list of GitHub usernames who have contributed to this article. -- `related`: Any related reading or useful examples. - -Note that `related` will generate a __Further Reading__ section at the bottom of the page and `contributors` will yield a __Contributors__ section below it. If you edit an article and would like recognition, don't hesitate to add your GitHub username to the `contributors` list. - - -## Article Structure - -1. Brief Introduction - a paragraph or two so you get the basic idea about the what and why. -2. Outline Remaining Content – how the content will be presented. -3. Main Content - tell what you promised to tell. -4. Conclusion - tell what you told and recap the main points. - - -## Typesetting - -- webpack should always be written in lower-case letters. Even at the beginning of a sentence. ([source](https://github.com/webpack/media#name)) -- loaders are enclosed in backticks and [kebab-cased](https://en.wikipedia.org/w/index.php?title=Kebab_case): `css-loader`, `ts-loader`, … -- plugins are enclosed in backticks and [camel-cased](https://en.wikipedia.org/wiki/Camel_case): `BannerPlugin`, `NpmInstallWebpackPlugin`, … -- Use "webpack 2" to refer to a specific webpack version (~~"webpack v2"~~) -- Use ES5; ES2015, ES2016, … to refer to the ECMAScript standards (~~ES6~~, ~~ES7~~) - - -## Formatting - -### Code - -__Syntax: \`\`\`javascript … \`\`\`__ - -```javascript -function foo () { - return 'bar'; -} - -foo(); -``` - -### Lists - -- Boo -- Foo -- Zoo - -Lists should be ordered alphabetically. - -### Tables - -Parameter | Explanation | Input Type | Default Value ------------ | ------------------------------------------------ | ---------- |-------------- ---debug | Switch loaders to debug mode | boolean | false ---devtool | Define source map type for the bundled resources | string | - ---progress | Print compilation progress in percentage | boolean | false - -Tables should also be ordered alphabetically. - -### Configuration Properties - -The [configuration](/configuration) properties should be ordered alphabetically as well: - -- `devServer.compress` -- `devServer.contentBase` -- `devServer.hot` - -### Quotes - -#### Blockquote - -__Syntax: \>__ - -> This is a blockquote. - -#### Tip - -__Syntax: T\>__ - -T> This is a tip. - -__Syntax: W\>__ - -W> This is a warning. - -__Syntax: ?\>__ - -?> This is a todo. - - -# Writing a Loader - -A loader is a node module that exports a function. This function is called when a resource should be transformed by this loader. The given function will have access to the [Loader API](/api/loaders/) using the `this` context provided to it. - - -## Setup - -Before we dig into the different types of loaders, their usage, and examples, let's take a look at the three ways you can develop and test a loader locally. - -To test a single loader, you can simply use `path` to `resolve` a local file within a rule object: - -__webpack.config.js__ - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - use: [ - { - loader: path.resolve('path/to/loader.js'), - options: {/* ... */} - } - ] - } - ] - } -}; -``` - -To test multiple, you can utilize the `resolveLoader.modules` configuration to update where webpack will search for loaders. For example, if you had a local `/loaders` directory in your project: - -__webpack.config.js__ - -```js -module.exports = { - //... - resolveLoader: { - modules: [ - 'node_modules', - path.resolve(__dirname, 'loaders') - ] - } -}; -``` - -Last but not least, if you've already created a separate repository and package for your loader, you could [`npm link`](https://docs.npmjs.com/cli/link) it to the project in which you'd like to test it out. - - -## Simple Usage - -When a single loader is applied to the resource, the loader is called with only one parameter -- a string containing the content of the resource file. - -Synchronous loaders can simply `return` a single value representing the transformed module. In more complex cases, the loader can return any number of values by using the `this.callback(err, values...)` function. Errors are either passed to the `this.callback` function or thrown in a sync loader. - -The loader is expected to give back one or two values. The first value is a resulting JavaScript code as string or buffer. The second optional value is a SourceMap as JavaScript object. - - -## Complex Usage - -When multiple loaders are chained, it is important to remember that they are executed in reverse order -- either right to left or bottom to top depending on array format. - -- The last loader, called first, will be passed the contents of the raw resource. -- The first loader, called last, is expected to return JavaScript and an optional source map. -- The loaders in between will be executed with the result(s) of the previous loader in the chain. - -So, in the following example, the `foo-loader` would be passed the raw resource and the `bar-loader` would receive the output of the `foo-loader` and return the final transformed module and a source map if necessary. - -__webpack.config.js__ - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js/, - use: [ - 'bar-loader', - 'foo-loader' - ] - } - ] - } -}; -``` - - -## Guidelines - -The following guidelines should be followed when writing a loader. They are ordered in terms of importance and some only apply in certain scenarios, read the detailed sections that follow for more information. - -- Keep them __simple__. -- Utilize __chaining__. -- Emit __modular__ output. -- Make sure they're __stateless__. -- Employ __loader utilities__. -- Mark __loader dependencies__. -- Resolve __module dependencies__. -- Extract __common code__. -- Avoid __absolute paths__. -- Use __peer dependencies__. - -### Simple - -Loaders should do only a single task. This not only makes the job of maintaining each loader easier, but also allows them to be chained for usage in more scenarios. - -### Chaining - -Take advantage of the fact that loaders can be chained together. Instead of writing a single loader that tackles five tasks, write five simpler loaders that divide this effort. Isolating them not only keeps each individual loader simple, but may allow for them to be used for something you hadn't thought of originally. - -Take the case of rendering a template file with data specified via loader options or query parameters. It could be written as a single loader that compiles the template from source, executes it and returns a module that exports a string containing the HTML code. However, in accordance with guidelines, a simple `apply-loader` exists that can be chained with other open source loaders: - -- `jade-loader`: Convert template to a module that exports a function. -- `apply-loader`: Executes the function with loader options and returns raw HTML. -- `html-loader`: Accepts HTML and outputs a valid JavaScript module. - -T> The fact that loaders can be chained also means they don't necessarily have to output JavaScript. As long as the next loader in the chain can handle its output, the loader can return any type of module. - -### Modular - -Keep the output modular. Loader generated modules should respect the same design principles as normal modules. - -### Stateless - -Make sure the loader does not retain state between module transformations. Each run should always be independent of other compiled modules as well as previous compilations of the same module. - -### Loader Utilities - -Take advantage of the [`loader-utils`](https://github.com/webpack/loader-utils) package. It provides a variety of useful tools but one of the most common is retrieving the options passed to the loader. Along with `loader-utils`, the [`schema-utils`](https://github.com/webpack-contrib/schema-utils) package should be used for consistent JSON Schema based validation of loader options. Here's a brief example that utilizes both: - -__loader.js__ - -```js -import { getOptions } from 'loader-utils'; -import validateOptions from 'schema-utils'; - -const schema = { - type: 'object', - properties: { - test: { - type: 'string' - } - } -}; - -export default function(source) { - const options = getOptions(this); - - validateOptions(schema, options, 'Example Loader'); - - // Apply some transformations to the source... - - return `export default ${ JSON.stringify(source) }`; -} -``` - -### Loader Dependencies - -If a loader uses external resources (i.e. by reading from filesystem), they __must__ indicate it. This information is used to invalidate cacheable loaders and recompile in watch mode. Here's a brief example of how to accomplish this using the `addDependency` method: - -__loader.js__ - -```js -import path from 'path'; - -export default function(source) { - var callback = this.async(); - var headerPath = path.resolve('header.js'); - - this.addDependency(headerPath); - - fs.readFile(headerPath, 'utf-8', function(err, header) { - if(err) return callback(err); - callback(null, header + '\n' + source); - }); -} -``` - -### Module Dependencies - -Depending on the type of module, there may be a different schema used to specify dependencies. In CSS for example, the `@import` and `url(...)` statements are used. These dependencies should be resolved by the module system. - -This can be done in one of two ways: - -- By transforming them to `require` statements. -- Using the `this.resolve` function to resolve the path. - -The `css-loader` is a good example of the first approach. It transforms dependencies to `require`s, by replacing `@import` statements with a `require` to the other stylesheet and `url(...)` with a `require` to the referenced file. - -In the case of the `less-loader`, it cannot transform each `@import` to a `require` because all `.less` files must be compiled in one pass for variables and mixin tracking. Therefore, the `less-loader` extends the less compiler with custom path resolving logic. It then takes advantage of the second approach, `this.resolve`, to resolve the dependency through webpack. - -T> If the language only accepts relative urls (e.g. `url(file)` always refers to `./file`), you can use the `~` convention to specify references to installed modules (e.g. those in `node_modules`). So, in the case of `url`, that would look something like `url('~some-library/image.jpg')`. - -### Common Code - -Avoid generating common code in every module the loader processes. Instead, create a runtime file in the loader and generate a `require` to that shared module. - -### Absolute Paths - -Don't insert absolute paths into the module code as they break hashing when the root for the project is moved. There's a [`stringifyRequest`](https://github.com/webpack/loader-utils#stringifyrequest) method in `loader-utils` which can be used to convert an absolute path to a relative one. - -### Peer Dependencies - -If the loader you're working on is a simple wrapper around another package, then you should include the package as a `peerDependency`. This approach allows the application's developer to specify the exact version in the `package.json` if desired. - -For instance, the `sass-loader` [specifies `node-sass`](https://github.com/webpack-contrib/sass-loader/blob/master/package.json) as peer dependency like so: - -```json -{ - "peerDependencies": { - "node-sass": "^4.0.0" - } -} -``` - - -## Testing - -So you've written a loader, followed the guidelines above, and have it set up to run locally. What's next? Let's go through a simple unit testing example to ensure our loader is working the way we expect. We'll be using the [Jest](https://facebook.github.io/jest/) framework to do this. We'll also install `babel-jest` and some presets that will allow us to use the `import` / `export` and `async` / `await`. Let's start by installing and saving these as a `devDependencies`: - -``` bash -npm install --save-dev jest babel-jest babel-preset-env -``` - -__.babelrc__ - -```json -{ - "presets": [[ - "env", - { - "targets": { - "node": "4" - } - } - ]] -} -``` - -Our loader will process `.txt` files and simply replace any instance of `[name]` with the `name` option given to the loader. Then it will output a valid JavaScript module containing the text as it's default export: - -__src/loader.js__ - -```js -import { getOptions } from 'loader-utils'; - -export default function loader(source) { - const options = getOptions(this); - - source = source.replace(/\[name\]/g, options.name); - - return `export default ${ JSON.stringify(source) }`; -} -``` - -We'll use this loader to process the following file: - -__test/example.txt__ - -``` text -Hey [name]! -``` - -Pay close attention to this next step as we'll be using the [Node.js API](/api/node) and [`memory-fs`](https://github.com/webpack/memory-fs) to execute webpack. This lets us avoid emitting `output` to disk and will give us access to the `stats` data which we can use to grab our transformed module: - -``` bash -npm install --save-dev webpack memory-fs -``` - -__test/compiler.js__ - -```js -import path from 'path'; -import webpack from 'webpack'; -import memoryfs from 'memory-fs'; - -export default (fixture, options = {}) => { - const compiler = webpack({ - context: __dirname, - entry: `./${fixture}`, - output: { - path: path.resolve(__dirname), - filename: 'bundle.js', - }, - module: { - rules: [{ - test: /\.txt$/, - use: { - loader: path.resolve(__dirname, '../src/loader.js'), - options: { - name: 'Alice' - } - } - }] - } - }); - - compiler.outputFileSystem = new memoryfs(); - - return new Promise((resolve, reject) => { - compiler.run((err, stats) => { - if (err || stats.hasErrors()) reject(err); - - resolve(stats); - }); - }); -}; -``` - -T> In this case, we've inlined our webpack configuration but you can also accept a configuration as a parameter to the exported function. This would allow you to test multiple setups using the same compiler module. - -And now, finally, we can write our test and add an npm script to run it: - -__test/loader.test.js__ - -```js -import compiler from './compiler.js'; - -test('Inserts name and outputs JavaScript', async () => { - const stats = await compiler('example.txt'); - const output = stats.toJson().modules[0].source; - - expect(output).toBe('export default "Hey Alice!\\n"'); -}); -``` - -__package.json__ - -```json -{ - "scripts": { - "test": "jest" - } -} -``` - -With everything in place, we can run it and see if our new loader passes the test: - -``` bash - PASS test/loader.test.js - ✓ Inserts name and outputs JavaScript (229ms) - -Test Suites: 1 passed, 1 total -Tests: 1 passed, 1 total -Snapshots: 0 total -Time: 1.853s, estimated 2s -Ran all test suites. -``` - -It worked! At this point you should be ready to start developing, testing, and deploying your own loaders. We hope that you'll share your creations with the rest of the community! - - -# Writing a Plugin - -Plugins expose the full potential of the webpack engine to third-party developers. Using staged build callbacks, developers can introduce their own behaviors into the webpack build process. Building plugins is a bit more advanced than building loaders, because you'll need to understand some of the webpack low-level internals to hook into them. Be prepared to read some source code! - -## Creating a Plugin - -A plugin for webpack consists of - -- A named JavaScript function. -- Defines `apply` method in its prototype. -- Specifies an [event hook](/api/compiler-hooks/) to tap into. -- Manipulates webpack internal instance specific data. -- Invokes webpack provided callback after functionality is complete. - -```javascript -// A JavaScript class. -class MyExampleWebpackPlugin { - // Define `apply` as its prototype method which is supplied with compiler as its argument - apply(compiler) { - // Specify the event hook to attach to - compiler.hooks.emit.tapAsync( - 'MyExampleWebpackPlugin', - (compilation, callback) => { - console.log('This is an example plugin!'); - console.log('Here’s the `compilation` object which represents a single build of assets:', compilation); - - // Manipulate the build using the plugin API provided by webpack - compilation.addModule(/* ... */); - - callback(); - } - ); - } -} -``` - -## Basic plugin architecture - -Plugins are instantiated objects with an `apply` method on their prototype. This `apply` method is called once by the webpack compiler while installing the plugin. The `apply` method is given a reference to the underlying webpack compiler, which grants access to compiler callbacks. A simple plugin is structured as follows: - -```javascript -class HelloWorldPlugin { - apply(compiler) { - compiler.hooks.done.tap('Hello World Plugin', ( - stats /* stats is passed as argument when done hook is tapped. */ - ) => { - console.log('Hello World!'); - }); - } -} - -module.exports = HelloWorldPlugin; -``` - -Then to use the plugin, include an instance in your webpack config `plugins` array: - -```javascript -// webpack.config.js -var HelloWorldPlugin = require('hello-world'); - -module.exports = { - // ... config settings here ... - plugins: [new HelloWorldPlugin({ options: true })] -}; -``` - -## Compiler and Compilation - -Among the two most important resources while developing plugins are the `compiler` and `compilation` objects. Understanding their roles is an important first step in extending the webpack engine. - -```javascript -class HelloCompilationPlugin { - apply(compiler) { - // Tap into compilation hook which gives compilation as argument to the callback function - compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => { - // Now we can tap into various hooks available through compilation - compilation.hooks.optimize.tap('HelloCompilationPlugin', () => { - console.log('Assets are being optimized.'); - }); - }); - } -} - -module.exports = HelloCompilationPlugin; -``` - -The list of hooks available on the `compiler`, `compilation`, and other important objects, see the [plugins API](/api/plugins/) docs. - -## Async event hooks - -Some plugin hooks are asynchronous. To tap into them, we can use `tap` method which will behave in synchronous manner or use one of `tapAsync` method or `tapPromise` method which are asynchronous methods. - -### tapAsync - -When we use `tapAsync` method to tap into plugins, we need to call the callback function which is supplied as the last argument to our function. - -```javascript -class HelloAsyncPlugin { - apply(compiler) { - compiler.hooks.emit.tapAsync('HelloAsyncPlugin', (compilation, callback) => { - // Do something async... - setTimeout(function() { - console.log('Done with async work...'); - callback(); - }, 1000); - }); - } -} - -module.exports = HelloAsyncPlugin; -``` - -#### tapPromise - -When we use `tapPromise` method to tap into plugins, we need to return a promise which resolves when our asynchronous task is completed. - -```javascript -class HelloAsyncPlugin { - apply(compiler) { - compiler.hooks.emit.tapPromise('HelloAsyncPlugin', compilation => { - // return a Promise that resolves when we are done... - return new Promise((resolve, reject) => { - setTimeout(function() { - console.log('Done with async work...'); - resolve(); - }, 1000); - }); - }); - } -} - -module.exports = HelloAsyncPlugin; -``` - -## Example - -Once we can latch onto the webpack compiler and each individual compilations, the possibilities become endless for what we can do with the engine itself. We can reformat existing files, create derivative files, or fabricate entirely new assets. - -Let's write a simple example plugin that generates a new build file called `filelist.md`; the contents of which will list all of the asset files in our build. This plugin might look something like this: - -```javascript -class FileListPlugin { - apply(compiler) { - // emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well - compiler.hooks.emit.tapAsync('FileListPlugin', (compilation, callback) => { - // Create a header string for the generated file: - var filelist = 'In this build:\n\n'; - - // Loop through all compiled assets, - // adding a new line item for each filename. - for (var filename in compilation.assets) { - filelist += '- ' + filename + '\n'; - } - - // Insert this list into the webpack build as a new file asset: - compilation.assets['filelist.md'] = { - source: function() { - return filelist; - }, - size: function() { - return filelist.length; - } - }; - - callback(); - }); - } -} - -module.exports = FileListPlugin; -``` - -## Different Plugin Shapes - -A plugin can be classified into types based on the event hooks it taps into. Every event hook is pre-defined as synchronous or asynchronous or waterfall or parallel hook and hook is called internally using call/callAsync method. The list of hooks that are supported or can be tapped into are generally specified in this.hooks property. - -For example:- - -```javascript -this.hooks = { - shouldEmit: new SyncBailHook(['compilation']) -}; -``` - -It represents that the only hook supported is `shouldEmit` which is a hook of `SyncBailHook` type and the only parameter which will be passed to any plugin that taps into `shouldEmit` hook is `compilation`. - -Various types of hooks supported are :- - -### Synchronous Hooks - -- __SyncHook__ - - - Defined as `new SyncHook([params])` - - Tapped into using `tap` method. - - Called using `call(...params)` method. - -- __Bail Hooks__ - - - Defined using `SyncBailHook[params]` - - Tapped into using `tap` method. - - Called using `call(...params)` method. - - In these type of hooks, each of the plugin callbacks will be invoked one after the other with the specific `args`. If any value is returned except undefined by any plugin, then that value is returned by hook and no further plugin callback is invoked. Many useful events like `optimizeChunks`, `optimizeChunkModules` are SyncBailHooks. - -- __Waterfall Hooks__ - - - Defined using `SyncWaterfallHook[params]` - - Tapped into using `tap` method. - - Called using `call( ... params)` method - - Here each of the plugins are called one after the other with the arguments from the return value of the previous plugin. The plugin must take the order of its execution into account. - It must accept arguments from the previous plugin that was executed. The value for the first plugin is `init`. Hence at least 1 param must be supplied for waterfall hooks. This pattern is used in the Tapable instances which are related to the webpack templates like `ModuleTemplate`, `ChunkTemplate` etc. - -### Asynchronous Hooks - -- __Async Series Hook__ - - - Defined using `AsyncSeriesHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - The plugin handler functions are called with all arguments and a callback function with the signature `(err?: Error) -> void`. The handler functions are called in order of registration. `callback` is called after all the handlers are called. - This is also a commonly used pattern for events like `emit`, `run`. - -- __Async waterfall__ The plugins will be applied asynchronously in the waterfall manner. - - - Defined using `AsyncWaterfallHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - The plugin handler functions are called with the current value and a callback function with the signature `(err: Error, nextValue: any) -> void.` When called `nextValue` is the current value for the next handler. The current value for the first handler is `init`. After all handlers are applied, callback is called with the last value. If any handler passes a value for `err`, the callback is called with this error and no more handlers are called. - This plugin pattern is expected for events like `before-resolve` and `after-resolve`. - -- __Async Series Bail__ - - - Defined using `AsyncSeriesBailHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - someMethod() { - // Call a hook: - this.hooks.compilation.call(); - -- __Async Parallel__ - - - Defined using `AsyncParallelHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - -- __Async Series Bail__ - - - Defined using `AsyncSeriesBailHook[params]` - - Tapped into using `tap`/`tapAsync`/`tapPromise` method. - - Called using `callAsync( ... params)` method - - -# Plugin Patterns - -Plugins grant unlimited opportunity to perform customizations within the webpack build system. This allows you to create custom asset types, perform unique build modifications, or even enhance the webpack runtime while using middleware. The following are some features of webpack that become useful while writing plugins. - -## Exploring assets, chunks, modules, and dependencies - -After a compilation is sealed, all structures within the compilation may be traversed. - -```javascript -class MyPlugin { - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - // Explore each chunk (build output): - compilation.chunks.forEach(chunk => { - // Explore each module within the chunk (built inputs): - chunk.modules.forEach(module => { - // Explore each source file path that was included into the module: - module.fileDependencies.forEach(filepath => { - // we've learned a lot about the source structure now... - }); - }); - - // Explore each asset filename generated by the chunk: - chunk.files.forEach(filename => { - // Get the asset source for each file generated by the chunk: - var source = compilation.assets[filename].source(); - }); - }); - - callback(); - }); - } -} -module.exports = MyPlugin; -``` - -- `compilation.modules`: An array of modules (built inputs) in the compilation. Each module manages the build of a raw file from your source library. -- `module.fileDependencies`: An array of source file paths included into a module. This includes the source JavaScript file itself (ex: `index.js`), and all dependency asset files (stylesheets, images, etc) that it has required. Reviewing dependencies is useful for seeing what source files belong to a module. -- `compilation.chunks`: An array of chunks (build outputs) in the compilation. Each chunk manages the composition of a final rendered assets. -- `chunk.modules`: An array of modules that are included into a chunk. By extension, you may look through each module's dependencies to see what raw source files fed into a chunk. -- `chunk.files`: An array of output filenames generated by the chunk. You may access these asset sources from the `compilation.assets` table. - -### Monitoring the watch graph - -While running webpack middleware, each compilation includes a `fileDependencies` array (what files are being watched) and a `fileTimestamps` hash that maps watched file paths to a timestamp. These are extremely useful for detecting what files have changed within the compilation: - -```javascript -class MyPlugin { - constructor() { - this.startTime = Date.now(); - this.prevTimestamps = {}; - } - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - var changedFiles = Object.keys(compilation.fileTimestamps).filter( - watchfile => { - return ( - (this.prevTimestamps[watchfile] || this.startTime) < - (compilation.fileTimestamps[watchfile] || Infinity) - ); - } - ); - - this.prevTimestamps = compilation.fileTimestamps; - callback(); - }); - } -} - -module.exports = MyPlugin; -``` - -You may also feed new file paths into the watch graph to receive compilation triggers when those files change. Simply push valid file paths into the `compilation.fileDependencies` array to add them to the watch. Note: the `fileDependencies` array is rebuilt in each compilation, so your plugin must push its own watched dependencies into each compilation to keep them under watch. - -## Changed chunks - -Similar to the watch graph, it's fairly simple to monitor changed chunks (or modules, for that matter) within a compilation by tracking their hashes. - -```javascript -class MyPlugin { - constructor() { - this.chunkVersions = {}; - } - apply(compiler) { - compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => { - var changedChunks = compilation.chunks.filter(chunk => { - var oldVersion = this.chunkVersions[chunk.name]; - this.chunkVersions[chunk.name] = chunk.hash; - return chunk.hash !== oldVersion; - }); - callback(); - }); - } -} - -module.exports = MyPlugin; -``` - - -# Release Process - -The release process for deploying webpack is actually quite painless. Read through the following steps, so you have a clear understanding of how it's done. - - -## Pull Requests - -When merging pull requests into the `master` branch, select the _Create Merge Commit_ option. - - -## Releasing - -```sh -npm version patch && git push --follow-tags && npm publish -npm version minor && git push --follow-tags && npm publish -npm version major && git push --follow-tags && npm publish -``` - -_This will increment the package version, commits the changes, cuts a __local tag__, push to github & publish the npm package._ - -After that go to the github [releases page](https://github.com/webpack/webpack/releases) and write a Changelog for the new tag. - - -# Debugging - -When contributing to the core repo, writing a loader/plugin, or even just working on complex project, debugging tools can be central to your workflow. Whether the problem is slow performance on a large project or an unhelpful traceback, the following utilities can make figuring it out less painful. - -- The [`stats` data](/api/stats) made available through [Node](/api/node#stats-object) and the [CLI](/api/cli#common-options). -- Chrome __DevTools__ via `node-nightly` and the latest Node.js versions. - - -## Stats - -Whether you want to sift through [this data](/api/stats) manually or use a tool to process it, the `stats` data can be extremely useful when debugging build issues. We won't go in depth here as there's an [entire page](/api/stats) dedicated to its contents, but know that you can use it to find the following information: - -- The contents of every module. -- The modules contained within every chunk. -- Per module compilation and resolving stats. -- Build errors and warnings. -- The relationships between modules. -- And much more... - -On top of that, the official [analyze tool](https://github.com/webpack/analyse) and [various others](/guides/code-splitting#bundle-analysis) will accept this data and visualize it in various ways. - - -## DevTools - -While [`console`](https://nodejs.org/api/console.html) statements may work well in simpler scenarios, sometimes a more robust solution is needed. As most front-end developers already know, Chrome DevTools are a life saver when debugging web applications, _but they don’t have to stop there_. As of Node v6.3.0+, developers can use the built-in `--inspect` flag to debug a node program in DevTools. - -This gives you the power to easily create breakpoints, debug memory usage, expose and examine objects in the console, and much more. In this short demo, we'll utilize the [`node-nightly`](https://github.com/hemanth/node-nightly) package which provides access to the latest and greatest inspecting capabilities. - -W> The `--inspect` interface has been available since v6.3.0 so feel to try it out with your local version, but be warned that certain features and flags may differ from the ones in this demo. - -Let's start by installing it globally: - -``` bash -npm install --global node-nightly -``` - -Now, we'll need to run it once to finish the installation: - -``` bash -node-nightly -``` - -Now, we can simply use `node-nightly` along with the `--inspect` flag to start our build in any webpack-based project. Note that we cannot run NPM `scripts`, e.g. `npm run build`, so we'll have specify the full `node_modules` path: - -``` bash -node-nightly --inspect ./node_modules/webpack/bin/webpack.js -``` - -Which should output something like: - -``` bash -Debugger listening on ws://127.0.0.1:9229/c624201a-250f-416e-a018-300bbec7be2c -For help see https://nodejs.org/en/docs/inspector -``` - -Now jump to `chrome://inspect` in the browser and you should see any active scripts you've inspected under the _Remote Target_ header. Click the "inspect" link under each script to open a dedicated debugger or the _Open dedicated DevTools for Node_ link for a session that will connect automatically. You can also check out the [NiM extension](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj), a handy Chrome plugin that will automatically open a DevTools tab every time you `--inspect` a script. - -We recommend using the `--inspect-brk` flag which will break on the first statement of the script allowing you to go through the source to set breakpoints and start/stop the build as you please. Also, don't forget that you can still pass arguments to the script. For example, if you have multiple configuration files you could pass `--config webpack.prod.js` to specify the configuration you'd like to debug. diff --git a/src/content/guides/_guides_all.md b/src/content/guides/_guides_all.md deleted file mode 100644 index dab542340ea2..000000000000 --- a/src/content/guides/_guides_all.md +++ /dev/null @@ -1,4880 +0,0 @@ - - -# Installation - -This guide goes through the various methods used to install webpack. - - -## Prerequisites - -Before we begin, make sure you have a fresh version of [Node.js](https://nodejs.org/en/) installed. The current Long Term Support (LTS) release is an ideal starting point. You may run into a variety of issues with the older versions as they may be missing functionality webpack and/or its related packages require. - - -## Local Installation - -The latest webpack release is: - -[](https://github.com/webpack/webpack/releases) - -To install the latest release or a specific version, run one of the following commands: - -``` bash -npm install --save-dev webpack -npm install --save-dev webpack@<version> -``` - -If you're using webpack v4 or later, you'll need to install the [CLI](/api/cli/). - -``` bash -npm install --save-dev webpack-cli -``` - -Installing locally is what we recommend for most projects. This makes it easier to upgrade projects individually when breaking changes are introduced. Typically webpack is run via one or more [npm scripts](https://docs.npmjs.com/misc/scripts) which will look for a webpack installation in your local `node_modules` directory: - -```json -"scripts": { - "start": "webpack --config webpack.config.js" -} -``` - -T> To run the local installation of webpack you can access its bin version as `node_modules/.bin/webpack`. - - -## Global Installation - -The following NPM installation will make `webpack` available globally: - -``` bash -npm install --global webpack -``` - -W> Note that this is __not a recommended practice__. Installing globally locks you down to a specific version of webpack and could fail in projects that use a different version. - - -## Bleeding Edge - -If you are enthusiastic about using the latest that webpack has to offer, you can install beta versions or even directly from the webpack repository using the following commands: - -``` bash -npm install webpack@beta -npm install webpack/webpack#<tagname/branchname> -``` - -W> Take caution when installing these bleeding edge releases! They may still contain bugs and therefore should not be used in production. - - -# Getting Started - -Webpack is used to compile JavaScript modules. Once [installed](/guides/installation), you can interface with webpack either from its [CLI](/api/cli) or [API](/api/node). If you're still new to webpack, please read through the [core concepts](/concepts) and [this comparison](/comparison) to learn why you might use it over the other tools that are out in the community. - -## Basic Setup - -First let's create a directory, initialize npm, [install webpack locally](/guides/installation#local-installation), and install the webpack-cli (the tool used to run webpack on the command line): - -``` bash -mkdir webpack-demo && cd webpack-demo -npm init -y -npm install webpack webpack-cli --save-dev -``` - -T> Throughout the Guides we will use `diff` blocks to show you what changes we're making to directories, files, and code. - -Now we'll create the following directory structure, files and their contents: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- index.html -+ |- /src -+ |- index.js -``` - -__src/index.js__ - -``` javascript -function component() { - let element = document.createElement('div'); - - // Lodash, currently included via a script, is required for this line to work - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; -} - -document.body.appendChild(component()); -``` - -__index.html__ - -``` html -<!doctype html> -<html> - <head> - <title>Getting Started</title> - <script src="https://unpkg.com/lodash@4.16.6"></script> - </head> - <body> - <script src="./src/index.js"></script> - </body> -</html> -``` - -We also need to adjust our `package.json` file in order to make sure we mark our package as `private`, as well as removing the `main` entry. This is to prevent an accidental publish of your code. - -T> If you want to learn more about the inner workings of `package.json`, then we recommend reading the [npm documentation](https://docs.npmjs.com/files/package.json). - -__package.json__ - -``` diff - { - "name": "webpack-demo", - "version": "1.0.0", - "description": "", -+ "private": true, -- "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "webpack": "^4.20.2", - "webpack-cli": "^3.1.2" - }, - "dependencies": {} - } -``` - -In this example, there are implicit dependencies between the `<script>` tags. Our `index.js` file depends on `lodash` being included in the page before it runs. This is because `index.js` never explicitly declared a need for `lodash`; it just assumes that the global variable `_` exists. - -There are problems with managing JavaScript projects this way: - -- It is not immediately apparent that the script depends on an external library. -- If a dependency is missing, or included in the wrong order, the application will not function properly. -- If a dependency is included but not used, the browser will be forced to download unnecessary code. - -Let's use webpack to manage these scripts instead. - -## Creating a Bundle - -First we'll tweak our directory structure slightly, separating the "source" code (`/src`) from our "distribution" code (`/dist`). The "source" code is the code that we'll write and edit. The "distribution" code is the minimized and optimized `output` of our build process that will eventually be loaded in the browser: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- /dist -+ |- index.html -- |- index.html - |- /src - |- index.js -``` - -To bundle the `lodash` dependency with `index.js`, we'll need to install the library locally: - -``` bash -npm install --save lodash -``` - -T> When installing a package that will be bundled into your production bundle, you should use `npm install --save`. If you're installing a package for development purposes (e.g. a linter, testing libraries, etc.) then you should use `npm install --save-dev`. More information can be found in the [npm documentation](https://docs.npmjs.com/cli/install). - -Now, lets import `lodash` in our script: - -__src/index.js__ - -``` diff -+ import _ from 'lodash'; -+ - function component() { - let element = document.createElement('div'); - -- // Lodash, currently included via a script, is required for this line to work - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -Now, since we'll be bundling our scripts, we have to update our `index.html` file. Let's remove the lodash `<script>`, as we now `import` it, and modify the other `<script>` tag to load the bundle, instead of the raw `/src` file: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> - <title>Getting Started</title> -- <script src="https://unpkg.com/lodash@4.16.6"></script> - </head> - <body> -- <script src="./src/index.js"></script> -+ <script src="main.js"></script> - </body> - </html> -``` - -In this setup, `index.js` explicitly requires `lodash` to be present, and binds it as `_` (no global scope pollution). By stating what dependencies a module needs, webpack can use this information to build a dependency graph. It then uses the graph to generate an optimized bundle where scripts will be executed in the correct order. - -With that said, let's run `npx webpack`, which will take our script at `src/index.js` as the [entry point](/concepts/entry-points), and will generate `dist/main.js` as the [output](/concepts/output). The `npx` command, which ships with Node 8.2/npm 5.2.0 or higher, runs the webpack binary (`./node_modules/.bin/webpack`) of the webpack package we installed in the beginning: - -``` bash -npx webpack - -... -Built at: 13/06/2018 11:52:07 - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ -``` - -T> Your output may vary a bit, but if the build is successful then you are good to go. Also, don't worry about the warning, we'll tackle that later. - -Open `index.html` in your browser and, if everything went right, you should see the following text: 'Hello webpack'. - - -## Modules - -The [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) statements have been standardized in [ES2015](https://babeljs.io/learn-es2015/) and [are supported in most browsers](https://caniuse.com/#search=modules). Some older browsers still lag behind but webpack supports modules out of the box. - -Behind the scenes, webpack actually "transpiles" the code so that older browsers can also run it. If you inspect `dist/main.js`, you might be able to see how webpack does this, it's quite ingenious! Besides `import` and `export`, webpack supports various other module syntaxes as well, see [Module API](/api/module-methods) for more information. - -Note that webpack will not alter any code other than `import` and `export` statements. If you are using other [ES2015 features](http://es6-features.org/), make sure to [use a transpiler](/loaders/#transpiling) such as [Babel](https://babeljs.io/) or [Bublé](https://buble.surge.sh/guide/) via webpack's [loader system](/concepts/loaders/). - - -## Using a Configuration - -As of version 4, webpack doesn't require any configuration, but most projects will need a more complex setup, which is why webpack supports a [configuration file](/concepts/configuration). This is much more efficient than having to manually type in a lot of commands in the terminal, so let's create one: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- webpack.config.js - |- /dist - |- index.html - |- /src - |- index.js -``` - -__webpack.config.js__ - -``` javascript -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'main.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -Now, let's run the build again but instead using our new configuration file: - -``` bash -npx webpack --config webpack.config.js - -... - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ -``` - -T> If a `webpack.config.js` is present, the `webpack` command picks it up by default. We use the `--config` option here only to show that you can pass a config of any name. This will be useful for more complex configurations that need to be split into multiple files. - -A configuration file allows far more flexibility than simple CLI usage. We can specify loader rules, plugins, resolve options and many other enhancements this way. See the [configuration documentation](/configuration) to learn more. - - -## NPM Scripts - -Given it's not particularly fun to run a local copy of webpack from the CLI, we can set up a little shortcut. Let's adjust our _package.json_ by adding an [npm script](https://docs.npmjs.com/misc/scripts): - -__package.json__ - -``` diff - { - "name": "webpack-demo", - "version": "1.0.0", - "description": "", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", -+ "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "webpack": "^4.20.2", - "webpack-cli": "^3.1.2" - }, - "dependencies": { - "lodash": "^4.17.5" - } - } -``` - -Now the `npm run build` command can be used in place of the `npx` command we used earlier. Note that within `scripts` we can reference locally installed npm packages by name the same way we did with `npx`. This convention is the standard in most npm-based projects because it allows all contributors to use the same set of common scripts (each with flags like `--config` if necessary). - -Now run the following command and see if your script alias works: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -main.js 70.4 KiB 0 [emitted] main -... - -WARNING in configuration -The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. -You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/. -``` - -T> Custom parameters can be passed to webpack by adding two dashes between the `npm run build` command and your parameters, e.g. `npm run build -- --colors`. - - -## Conclusion - -Now that you have a basic build together you should move on to the next guide [`Asset Management`](/guides/asset-management) to learn how to manage assets like images and fonts with webpack. At this point, your project should look like this: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist - |- main.js - |- index.html -|- /src - |- index.js -|- /node_modules -``` - -T> If you're using npm 5, you'll probably also see a `package-lock.json` file in your directory. - -If you want to learn more about webpack's design, you can check out the [basic concepts](/concepts) and [configuration](/configuration) pages. Furthermore, the [API](/api) section digs into the various interfaces webpack offers. - - -# Asset Management - -If you've been following the guides from the start, you will now have a small project that shows "Hello webpack". Now let's try to incorporate some other assets, like images, to see how they can be handled. - -Prior to webpack, front-end developers would use tools like grunt and gulp to process these assets and move them from their `/src` folder into their `/dist` or `/build` directory. The same idea was used for JavaScript modules, but tools like webpack will __dynamically bundle__ all dependencies (creating what's known as a [dependency graph](/concepts/dependency-graph)). This is great because every module now _explicitly states its dependencies_ and we'll avoid bundling modules that aren't in use. - -One of the coolest webpack features is that you can also _include any other type of file_, besides JavaScript, for which there is a loader. This means that the same benefits listed above for JavaScript (e.g. explicit dependencies) can be applied to everything used in building a website or web app. Let's start with CSS, as you may already be familiar with that setup. - -## Setup - -Let's make a minor change to our project before we get started: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> -- <title>Getting Started</title> -+ <title>Asset Management</title> - </head> - <body> -- <script src="./main.js"></script> -+ <script src="./bundle.js"></script> - </body> - </html> -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { -- filename: 'main.js', -+ filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - - -## Loading CSS - -In order to `import` a CSS file from within a JavaScript module, you need to install and add the [style-loader](/loaders/style-loader) and [css-loader](/loaders/css-loader) to your [`module` configuration](/configuration/module): - -``` bash -npm install --save-dev style-loader css-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ module: { -+ rules: [ -+ { -+ test: /\.css$/, -+ use: [ -+ 'style-loader', -+ 'css-loader' -+ ] -+ } -+ ] -+ } - }; -``` - -T> webpack uses a regular expression to determine which files it should look for and serve to a specific loader. In this case any file that ends with `.css` will be served to the `style-loader` and the `css-loader`. - -This enables you to `import './style.css'` into the file that depends on that styling. Now, when that module is run, a `<style>` tag with the stringified css will be inserted into the `<head>` of your html file. - -Let's try it out by adding a new `style.css` file to our project and import it in our `index.js`: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- style.css - |- index.js - |- /node_modules -``` - -__src/style.css__ - -``` css -.hello { - color: red; -} -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import './style.css'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.classList.add('hello'); - - return element; - } - - document.body.appendChild(component()); -``` - -Now run your build command: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -bundle.js 76.4 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -Open up `index.html` in your browser again and you should see that `Hello webpack` is now styled in red. To see what webpack did, inspect the page (don't view the page source, as it won't show you the result) and look at the page's head tags. It should contain our style block that we imported in `index.js`. - -Note that you can, and in most cases should, [minimize css](/plugins/mini-css-extract-plugin/#minimizing-for-production) for better load times in production. On top of that, loaders exist for pretty much any flavor of CSS you can think of -- [postcss](/loaders/postcss-loader), [sass](/loaders/sass-loader), and [less](/loaders/less-loader) to name a few. - - -## Loading Images - -So now we're pulling in our CSS, but what about our images like backgrounds and icons? Using the [file-loader](/loaders/file-loader) we can easily incorporate those in our system as well: - -``` bash -npm install --save-dev file-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, -+ { -+ test: /\.(png|svg|jpg|gif)$/, -+ use: [ -+ 'file-loader' -+ ] -+ } - ] - } - }; -``` - -Now, when you `import MyImage from './my-image.png'`, that image will be processed and added to your `output` directory _and_ the `MyImage` variable will contain the final url of that image after processing. When using the [css-loader](/loaders/css-loader), as shown above, a similar process will occur for `url('./my-image.png')` within your CSS. The loader will recognize this is a local file, and replace the `'./my-image.png'` path with the final path to the image in your `output` directory. The [html-loader](/loaders/html-loader) handles `<img src="./my-image.png" />` in the same manner. - -Let's add an image to our project and see how this works, you can use any image you like: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; - import './style.css'; -+ import Icon from './icon.png'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - element.classList.add('hello'); - -+ // Add the image to our existing div. -+ var myIcon = new Image(); -+ myIcon.src = Icon; -+ -+ element.appendChild(myIcon); - - return element; - } - - document.body.appendChild(component()); -``` - -__src/style.css__ - -``` diff - .hello { - color: red; -+ background: url('./icon.png'); - } -``` - -Let's create a new build and open up the index.html file again: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] - bundle.js 76.7 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -If all went well, you should now see your icon as a repeating background, as well as an `img` element beside our `Hello webpack` text. If you inspect this element, you'll see that the actual filename has changed to something like `5c999da72346a995e7e2718865d019c8.png`. This means webpack found our file in the `src` folder and processed it! - -T> A logical next step from here is minifying and optimizing your images. Check out the [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader) and [url-loader](/loaders/url-loader) for more on how you can enhance your image loading process. - - -## Loading Fonts - -So what about other assets like fonts? The file and url loaders will take any file you load through them and output it to your build directory. This means we can use them for any kind of file, including fonts. Let's update our `webpack.config.js` to handle font files: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, - { - test: /\.(png|svg|jpg|gif)$/, - use: [ - 'file-loader' - ] - }, -+ { -+ test: /\.(woff|woff2|eot|ttf|otf)$/, -+ use: [ -+ 'file-loader' -+ ] -+ } - ] - } - }; -``` - -Add some font files to your project: - -__project__ - - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- my-font.woff -+ |- my-font.woff2 - |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -With the loader configured and fonts in place, you can incorporate them via an `@font-face` declaration. The local `url(...)` directive will be picked up by webpack just as it was with the image: - -__src/style.css__ - -``` diff -+ @font-face { -+ font-family: 'MyFont'; -+ src: url('./my-font.woff2') format('woff2'), -+ url('./my-font.woff') format('woff'); -+ font-weight: 600; -+ font-style: normal; -+ } - - .hello { - color: red; -+ font-family: 'MyFont'; - background: url('./icon.png'); - } -``` - -Now run a new build and let's see if webpack handled our fonts: - -``` bash -npm run build - -... - Asset Size Chunks Chunk Names -5439466351d432b73fdb518c6ae9654a.woff2 19.5 KiB [emitted] - 387c65cc923ad19790469cfb5b7cb583.woff 23.4 KiB [emitted] - da4574bb234ddc4bb47cbe1ca4b20303.png 3.01 MiB [emitted] [big] - bundle.js 77 KiB 0 [emitted] main -Entrypoint main = bundle.js -... -``` - -Open up `index.html` again and see if our `Hello webpack` text has changed to the new font. If all is well, you should see the changes. - - -## Loading Data - -Another useful asset that can be loaded is data, like JSON files, CSVs, TSVs, and XML. Support for JSON is actually built-in, similar to NodeJS, meaning `import Data from './data.json'` will work by default. To import CSVs, TSVs, and XML you could use the [csv-loader](https://github.com/theplatapi/csv-loader) and [xml-loader](https://github.com/gisikw/xml-loader). Let's handle loading all three: - -``` bash -npm install --save-dev csv-loader xml-loader -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ] - }, - { - test: /\.(png|svg|jpg|gif)$/, - use: [ - 'file-loader' - ] - }, - { - test: /\.(woff|woff2|eot|ttf|otf)$/, - use: [ - 'file-loader' - ] - }, -+ { -+ test: /\.(csv|tsv)$/, -+ use: [ -+ 'csv-loader' -+ ] -+ }, -+ { -+ test: /\.xml$/, -+ use: [ -+ 'xml-loader' -+ ] -+ } - ] - } - }; -``` - -Add some data files to your project: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -+ |- data.xml - |- my-font.woff - |- my-font.woff2 - |- icon.png - |- style.css - |- index.js - |- /node_modules -``` - -__src/data.xml__ - -``` xml -<?xml version="1.0" encoding="UTF-8"?> -<note> - <to>Mary</to> - <from>John</from> - <heading>Reminder</heading> - <body>Call Cindy on Tuesday</body> -</note> -``` - -Now you can `import` any one of those four types of data (JSON, CSV, TSV, XML) and the `Data` variable you import it to will contain parsed JSON for easy consumption: - -__src/index.js__ - -``` diff - import _ from 'lodash'; - import './style.css'; - import Icon from './icon.png'; -+ import Data from './data.xml'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - element.classList.add('hello'); - - // Add the image to our existing div. - var myIcon = new Image(); - myIcon.src = Icon; - - element.appendChild(myIcon); - -+ console.log(Data); - - return element; - } - - document.body.appendChild(component()); -``` - -When you open `index.html` and look at your console in your developer tools, you should be able to see your imported data being logged to the console! - -T> This can be especially helpful when implementing some sort of data visualization using a tool like [d3](https://github.com/d3). Instead of making an ajax request and parsing the data at runtime you can load it into your module during the build process so that the parsed data is ready to go as soon as the module hits the browser. - - -## Global Assets - -The coolest part of everything mentioned above, is that loading assets this way allows you to group modules and assets together in a more intuitive way. Instead of relying on a global `/assets` directory that contains everything, you can group assets with the code that uses them. For example, a structure like this can be very useful: - -``` diff -- |- /assets -+ |– /components -+ | |– /my-component -+ | | |– index.jsx -+ | | |– index.css -+ | | |– icon.svg -+ | | |– img.png -``` - -This setup makes your code a lot more portable as everything that is closely coupled now lives together. Let's say you want to use `/my-component` in another project, simply copy or move it into the `/components` directory over there. As long as you've installed any _external dependencies_ and your _configuration has the same loaders_ defined, you should be good to go. - -However, let's say you're locked into your old ways or you have some assets that are shared between multiple components (views, templates, modules, etc.). It's still possible to store these assets in a base directory and even use [aliasing](/configuration/resolve#resolve-alias) to make them easier to `import`. - - -## Wrapping up - -For the next guides we won't be using all the different assets we've used in this guide, so let's do some cleanup so we're prepared for the next piece of the guides [Output Management](https://webpack.js.org/guides/output-management/): - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src -- |- data.xml -- |- my-font.woff -- |- my-font.woff2 -- |- icon.png -- |- style.css - |- index.js - |- /node_modules -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- module: { -- rules: [ -- { -- test: /\.css$/, -- use: [ -- 'style-loader', -- 'css-loader' -- ] -- }, -- { -- test: /\.(png|svg|jpg|gif)$/, -- use: [ -- 'file-loader' -- ] -- }, -- { -- test: /\.(woff|woff2|eot|ttf|otf)$/, -- use: [ -- 'file-loader' -- ] -- }, -- { -- test: /\.(csv|tsv)$/, -- use: [ -- 'csv-loader' -- ] -- }, -- { -- test: /\.xml$/, -- use: [ -- 'xml-loader' -- ] -- } -- ] -- } - }; -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -- import './style.css'; -- import Icon from './icon.png'; -- import Data from './data.xml'; -- - function component() { - var element = document.createElement('div'); -- -- // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- element.classList.add('hello'); -- -- // Add the image to our existing div. -- var myIcon = new Image(); -- myIcon.src = Icon; -- -- element.appendChild(myIcon); -- -- console.log(Data); - - return element; - } - - document.body.appendChild(component()); -``` - - -## Next guide - -Let's move on to [Output Management](https://webpack.js.org/guides/output-management/) - - -## Further Reading - -- [Loading Fonts](https://survivejs.com/webpack/loading/fonts/) on SurviveJS - - -# Output Management - -T> This guide extends on code examples found in the [`Asset Management`](/guides/asset-management) guide. - -So far we've manually included all our assets in our `index.html` file, but as your application grows and once you start [using hashes in filenames](/guides/caching) and outputting [multiple bundles](/guides/code-splitting), it will be difficult to keep managing your `index.html` file manually. However, a few plugins exist that will make this process much easier to manage. - -## Preparation - -First, let's adjust our project a little bit: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js -+ |- print.js - |- /node_modules -``` - -Let's add some logic to our `src/print.js` file: - -__src/print.js__ - -``` js -export default function printMe() { - console.log('I get called from print.js!'); -} -``` - -And use that function in our `src/index.js` file: - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); -+ var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - -+ btn.innerHTML = 'Click me and check the console!'; -+ btn.onclick = printMe; -+ -+ element.appendChild(btn); - - return element; - } - - document.body.appendChild(component()); -``` - -Let's also update our `dist/index.html` file, in preparation for webpack to split out entries: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> -- <title>Asset Management</title> -+ <title>Output Management</title> -+ <script src="./print.bundle.js"></script> - </head> - <body> -- <script src="./bundle.js"></script> -+ <script src="./app.bundle.js"></script> - </body> - </html> -``` - -Now adjust the config. We'll be adding our `src/print.js` as a new entry point (`print`) and we'll change the output as well, so that it will dynamically generate bundle names, based on the entry point names: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { -- entry: './src/index.js', -+ entry: { -+ app: './src/index.js', -+ print: './src/print.js' -+ }, - output: { -- filename: 'bundle.js', -+ filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Let's run `npm run build` and see what this generates: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 545 kB 0, 1 [emitted] [big] app -print.bundle.js 2.74 kB 1 [emitted] print -... -``` - -We can see that webpack generates our `print.bundle.js` and `app.bundle.js` files, which we also specified in our `index.html` file. if you open `index.html` in your browser, you can see what happens when you click the button. - -But what would happen if we changed the name of one of our entry points, or even added a new one? The generated bundles would be renamed on a build, but our `index.html` file would still reference the old names. Let's fix that with the [`HtmlWebpackPlugin`](/plugins/html-webpack-plugin). - - -## Setting up HtmlWebpackPlugin - -First install the plugin and adjust the `webpack.config.js` file: - -``` bash -npm install --save-dev html-webpack-plugin -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, -+ plugins: [ -+ new HtmlWebpackPlugin({ -+ title: 'Output Management' -+ }) -+ ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Before we do a build, you should know that the `HtmlWebpackPlugin` by default will generate its own `index.html` file, even though we already have one in the `dist/` folder. This means that it will replace our `index.html` file with a newly generated one. Let's see what happens when we do an `npm run build`: - -``` bash -... - Asset Size Chunks Chunk Names - print.bundle.js 544 kB 0 [emitted] [big] print - app.bundle.js 2.81 kB 1 [emitted] app - index.html 249 bytes [emitted] -... -``` - -If you open `index.html` in your code editor, you'll see that the `HtmlWebpackPlugin` has created an entirely new file for you and that all the bundles are automatically added. - -If you want to learn more about all the features and options that the `HtmlWebpackPlugin` provides, then you should read up on it on the [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin) repo. - -You can also take a look at [`html-webpack-template`](https://github.com/jaketrent/html-webpack-template) which provides a couple of extra features in addition to the default template. - - -## Cleaning up the `/dist` folder - -As you might have noticed over the past guides and code example, our `/dist` folder has become quite cluttered. Webpack will generate the files and put them in the `/dist` folder for you, but it doesn't keep track of which files are actually in use by your project. - -In general it's good practice to clean the `/dist` folder before each build, so that only used files will be generated. Let's take care of that. - -A popular plugin to manage this is the [`clean-webpack-plugin`](https://www.npmjs.com/package/clean-webpack-plugin) so let's install and configure it. - -``` bash -npm install --save-dev clean-webpack-plugin -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); -+ const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ -+ new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Output Management' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Now run an `npm run build` and inspect the `/dist` folder. If everything went well you should now only see the files generated from the build and no more old files! - - -## The Manifest - -You might be wondering how webpack and its plugins seem to "know" what files are being generated. The answer is in the manifest that webpack keeps to track how all the modules map to the output bundles. If you're interested in managing webpack's [`output`](/configuration/output) in other ways, the manifest would be a good place to start. - -The manifest data can be extracted into a json file for easy consumption using the [`WebpackManifestPlugin`](https://github.com/danethurber/webpack-manifest-plugin). - -We won't go through a full example of how to use this plugin within your projects, but you can read up on [the concept page](/concepts/manifest) and the [caching guide](/guides/caching) to find out how this ties into long term caching. - - -## Conclusion - -Now that you've learned about dynamically adding bundles to your HTML, let's dive into the [development guide](/guides/development). Or, if you want to dig into more advanced topics, we would recommend heading over to the [code splitting guide](/guides/code-splitting). - - -# Development - -T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. - -If you've been following the guides, you should have a solid understanding of some of the webpack basics. Before we continue, let's look into setting up a development environment to make our lives a little easier. - -W> The tools in this guide are __only meant for development__, please __avoid__ using them in production! - -Before proceeding lets first set [`mode` to `'development'`](/concepts/mode/#mode-development). - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { -+ mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -## Using source maps - -When webpack bundles your source code, it can become difficult to track down errors and warnings to their original location. For example, if you bundle three source files (`a.js`, `b.js`, and `c.js`) into one bundle (`bundle.js`) and one of the source files contains an error, the stack trace will simply point to `bundle.js`. This isn't always helpful as you probably want to know exactly which source file the error came from. - -In order to make it easier to track down errors and warnings, JavaScript offers [source maps](http://blog.teamtreehouse.com/introduction-source-maps), which maps your compiled code back to your original source code. If an error originates from `b.js`, the source map will tell you exactly that. - -There are a lot of [different options](/configuration/devtool) available when it comes to source maps. Be sure to check them out so you can configure them to your needs. - -For this guide, let's use the `inline-source-map` option, which is good for illustrative purposes (though not for production): - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, -+ devtool: 'inline-source-map', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Now let's make sure we have something to debug, so let's create an error in our `print.js` file: - -__src/print.js__ - -``` diff - export default function printMe() { -- console.log('I get called from print.js!'); -+ cosnole.log('I get called from print.js!'); - } -``` - -Run an `npm run build`, it should compile to something like this: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 1.44 MB 0, 1 [emitted] [big] app -print.bundle.js 6.43 kB 1 [emitted] print - index.html 248 bytes [emitted] -... -``` - -Now open the resulting `index.html` file in your browser. Click the button and look in your console where the error is displayed. The error should say something like this: - - ``` bash - Uncaught ReferenceError: cosnole is not defined - at HTMLButtonElement.printMe (print.js:2) - ``` - -We can see that the error also contains a reference to the file (`print.js`) and line number (2) where the error occurred. This is great because now we know exactly where to look in order to fix the issue. - - -## Choosing a Development Tool - -W> Some text editors have a "safe write" function that might interfere with some of the following tools. Read [Adjusting Your text Editor](#adjusting-your-text-editor) for a solution to these issues. - -It quickly becomes a hassle to manually run `npm run build` every time you want to compile your code. - -There are a couple of different options available in webpack that help you automatically compile your code whenever it changes: - - 1. webpack's Watch Mode - 2. webpack-dev-server - 3. webpack-dev-middleware - -In most cases, you probably would want to use `webpack-dev-server`, but let's explore all of the above options. - - -### Using Watch Mode - -You can instruct webpack to "watch" all files within your dependency graph for changes. If one of these files is updated, the code will be recompiled so you don't have to run the full build manually. - -Let's add an npm script that will start webpack's Watch Mode: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", -+ "watch": "webpack --watch", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now run `npm run watch` from the command line and see how webpack compiles your code. -You can see that it doesn't exit the command line because the script is currently watching your files. - -Now, while webpack is watching your files, let's remove the error we introduced earlier: - -__src/print.js__ - -``` diff - export default function printMe() { -- cosnole.log('I get called from print.js!'); -+ console.log('I get called from print.js!'); - } -``` - -Now save your file and check the terminal window. You should see that webpack automatically recompiles the changed module! - -The only downside is that you have to refresh your browser in order to see the changes. It would be much nicer if that would happen automatically as well, so let's try `webpack-dev-server` which will do exactly that. - - -### Using webpack-dev-server - -The `webpack-dev-server` provides you with a simple web server and the ability to use live reloading. Let's set it up: - -``` bash -npm install --save-dev webpack-dev-server -``` - -Change your config file to tell the dev server where to look for files: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - devtool: 'inline-source-map', -+ devServer: { -+ contentBase: './dist' -+ }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Development' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -This tells `webpack-dev-server` to serve the files from the `dist` directory on `localhost:8080`. - -W> webpack-dev-server doesn't write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server's root path. If your page expects to find the bundle files in different path, you can change this with the [`publicPath`](/configuration/dev-server/#devserver-publicpath-) option in the dev server's configuration. - -Let's add a script to easily run the dev server as well: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "watch": "webpack --watch", -+ "start": "webpack-dev-server --open", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now we can run `npm start` from the command line and we will see our browser automatically loading up our page. If you now change any of the source files and save them, the web server will automatically reload after the code has been compiled. Give it a try! - -The `webpack-dev-server` comes with many configurable options. Head over to the [documentation](/configuration/dev-server) to learn more. - -T> Now that your server is working, you might want to give [Hot Module Replacement](/guides/hot-module-replacement) a try! - - -### Using webpack-dev-middleware - -`webpack-dev-middleware` is a wrapper that will emit files processed by webpack to a server. This is used in `webpack-dev-server` internally, however it's available as a separate package to allow more custom setups if desired. We'll take a look at an example that combines webpack-dev-middleware with an express server. - -Let's install `express` and `webpack-dev-middleware` so we can get started: - -``` bash -npm install --save-dev express webpack-dev-middleware -``` - -Now we need to make some adjustments to our webpack configuration file in order to make sure the middleware will function correctly: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - - module.exports = { - mode: 'development', - entry: { - app: './src/index.js', - print: './src/print.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Output Management' - }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist'), -+ publicPath: '/' - } - }; -``` - -The `publicPath` will be used within our server script as well in order to make sure files are served correctly on `http://localhost:3000`. We'll specify the port number later. The next step is setting up our custom `express` server: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js -+ |- server.js - |- /dist - |- /src - |- index.js - |- print.js - |- /node_modules -``` - -__server.js__ - -```javascript -const express = require('express'); -const webpack = require('webpack'); -const webpackDevMiddleware = require('webpack-dev-middleware'); - -const app = express(); -const config = require('./webpack.config.js'); -const compiler = webpack(config); - -// Tell express to use the webpack-dev-middleware and use the webpack.config.js -// configuration file as a base. -app.use(webpackDevMiddleware(compiler, { - publicPath: config.output.publicPath -})); - -// Serve the files on port 3000. -app.listen(3000, function () { - console.log('Example app listening on port 3000!\n'); -}); -``` - -Now add an npm script to make it a little easier to run the server: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "webpack.config.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "watch": "webpack --watch", - "start": "webpack-dev-server --open", -+ "server": "node server.js", - "build": "webpack" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.16", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "express": "^4.15.3", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "webpack-dev-middleware": "^1.12.0", - "xml-loader": "^1.2.1" - } - } -``` - -Now in your terminal run `npm run server`, it should give you an output similar to this: - -``` bash -Example app listening on port 3000! -... - Asset Size Chunks Chunk Names - app.bundle.js 1.44 MB 0, 1 [emitted] [big] app -print.bundle.js 6.57 kB 1 [emitted] print - index.html 306 bytes [emitted] -... -webpack: Compiled successfully. -``` - -Now fire up your browser and go to `http://localhost:3000`. You should see your webpack app running and functioning! - -T> If you would like to know more about how Hot Module Replacement works, we recommend you read the [Hot Module Replacement](/guides/hot-module-replacement/) guide. - - -## Adjusting Your Text Editor - -When using automatic compilation of your code, you could run into issues when saving your files. Some editors have a "safe write" feature that can potentially interfere with recompilation. - -To disable this feature in some common editors, see the list below: - -- __Sublime Text 3__: Add `atomic_save: 'false'` to your user preferences. -- __JetBrains IDEs (e.g. WebStorm)__: Uncheck "Use safe write" in `Preferences > Appearance & Behavior > System Settings`. -- __Vim__: Add `:set backupcopy=yes` to your settings. - - -## Conclusion - -Now that you've learned how to automatically compile your code and run a simple development server, you can check out the next guide, which will cover [Hot Module Replacement](/guides/hot-module-replacement). - - -# Hot Module Replacement - -T> This guide extends on code examples found in the [Development](/guides/development) guide. - -Hot Module Replacement (or HMR) is one of the most useful features offered by webpack. It allows all kinds of modules to be updated at runtime without the need for a full refresh. This page focuses on __implementation__ while the [concepts page](/concepts/hot-module-replacement) gives more details on how it works and why it's useful. - -W> __HMR__ is not intended for use in production, meaning it should only be used in development. See the [building for production guide](/guides/production) for more information. - - -## Enabling HMR - -This feature is great for productivity. All we need to do is update our [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration, and use webpack's built in HMR plugin. We'll also remove the entry point for `print.js` as it will now be consumed by the `index.js` module. - -T> If you took the route of using `webpack-dev-middleware` instead of `webpack-dev-server`, please use the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom server or application. - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const webpack = require('webpack'); - - module.exports = { - entry: { -- app: './src/index.js', -- print: './src/print.js' -+ app: './src/index.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist', -+ hot: true - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Hot Module Replacement' - }), -+ new webpack.HotModuleReplacementPlugin() - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -T> You can use the CLI to modify the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) configuration with the following command: `webpack-dev-server --hotOnly`. - -Now let's update the `index.js` file so that when a change inside `print.js` is detected we tell webpack to accept the updated module. - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; - - element.appendChild(btn); - - return element; - } - - document.body.appendChild(component()); -+ -+ if (module.hot) { -+ module.hot.accept('./print.js', function() { -+ console.log('Accepting the updated printMe module!'); -+ printMe(); -+ }) -+ } -``` - -Start changing the `console.log` statement in `print.js`, and you should see the following output in the browser console. - -__print.js__ - -``` diff - export default function printMe() { -- console.log('I get called from print.js!'); -+ console.log('Updating print.js...') - } -``` - -__console__ - -``` diff -[HMR] Waiting for update signal from WDS... -main.js:4395 [WDS] Hot Module Replacement enabled. -+ 2main.js:4395 [WDS] App updated. Recompiling... -+ main.js:4395 [WDS] App hot update... -+ main.js:4330 [HMR] Checking for updates on the server... -+ main.js:10024 Accepting the updated printMe module! -+ 0.4b8ee77….hot-update.js:10 Updating print.js... -+ main.js:4330 [HMR] Updated modules: -+ main.js:4330 [HMR] - 20 -``` - - -## Via the Node.js API - -When using Webpack Dev Server with the Node.js API, don't put the dev server options on the webpack config object. Instead, pass them as a second parameter upon creation. For example: - -`new WebpackDevServer(compiler, options)` - -To enable HMR, you also need to modify your webpack configuration object to include the HMR entry points. The `webpack-dev-server` package includes a method called `addDevServerEntrypoints` which you can use to do this. Here's a small example of how that might look: - -__dev-server.js__ - -``` javascript -const webpackDevServer = require('webpack-dev-server'); -const webpack = require('webpack'); - -const config = require('./webpack.config.js'); -const options = { - contentBase: './dist', - hot: true, - host: 'localhost' -}; - -webpackDevServer.addDevServerEntrypoints(config, options); -const compiler = webpack(config); -const server = new webpackDevServer(compiler, options); - -server.listen(5000, 'localhost', () => { - console.log('dev server listening on port 5000'); -}); -``` - -T> If you're [using `webpack-dev-middleware`](/guides/development#using-webpack-dev-middleware), check out the [`webpack-hot-middleware`](https://github.com/webpack-contrib/webpack-hot-middleware) package to enable HMR on your custom dev server. - - -## Gotchas - -Hot Module Replacement can be tricky. To show this, let's go back to our working example. If you go ahead and click the button on the example page, you will realize the console is printing the old `printMe` function. - -This is happening because the button's `onclick` event handler is still bound to the original `printMe` function. - -To make this work with HMR we need to update that binding to the new `printMe` function using `module.hot.accept`: - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; // onclick event is bind to the original printMe function - - element.appendChild(btn); - - return element; - } - -- document.body.appendChild(component()); -+ let element = component(); // Store the element to re-render on print.js changes -+ document.body.appendChild(element); - - if (module.hot) { - module.hot.accept('./print.js', function() { - console.log('Accepting the updated printMe module!'); -- printMe(); -+ document.body.removeChild(element); -+ element = component(); // Re-render the "component" to update the click handler -+ document.body.appendChild(element); - }) - } -``` - -This is just one example, but there are many others that can easily trip people up. Luckily, there are a lot of loaders out there (some of which are mentioned below) that will make hot module replacement much easier. - - -## HMR with Stylesheets - -Hot Module Replacement with CSS is actually fairly straightforward with the help of the `style-loader`. This loader uses `module.hot.accept` behind the scenes to patch `<style>` tags when CSS dependencies are updated. - -First let's install both loaders with the following command: - -```bash -npm install --save-dev style-loader css-loader -``` - -Now let's update the configuration file to make use of the loader. - -__webpack.config.js__ - -```diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const webpack = require('webpack'); - - module.exports = { - entry: { - app: './src/index.js' - }, - devtool: 'inline-source-map', - devServer: { - contentBase: './dist', - hot: true - }, -+ module: { -+ rules: [ -+ { -+ test: /\.css$/, -+ use: ['style-loader', 'css-loader'] -+ } -+ ] -+ }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Hot Module Replacement' - }), - new webpack.HotModuleReplacementPlugin() - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Hot loading stylesheets is as easy as importing them into a module: - -__project__ - -``` diff - webpack-demo - | - package.json - | - webpack.config.js - | - /dist - | - bundle.js - | - /src - | - index.js - | - print.js -+ | - styles.css -``` - -__styles.css__ - -``` css -body { - background: blue; -} -``` - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; -+ import './styles.css'; - - function component() { - var element = document.createElement('div'); - var btn = document.createElement('button'); - - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - btn.innerHTML = 'Click me and check the console!'; - btn.onclick = printMe; // onclick event is bind to the original printMe function - - element.appendChild(btn); - - return element; - } - - let element = component(); - document.body.appendChild(element); - - if (module.hot) { - module.hot.accept('./print.js', function() { - console.log('Accepting the updated printMe module!'); - document.body.removeChild(element); - element = component(); // Re-render the "component" to update the click handler - document.body.appendChild(element); - }) - } - -``` - -Change the style on `body` to `background: red;` and you should immediately see the page's background color change without a full refresh. - -__styles.css__ - -``` diff - body { -- background: blue; -+ background: red; - } -``` - - -## Other Code and Frameworks - -There are many other loaders and examples out in the community to make HMR interact smoothly with a variety of frameworks and libraries... - -- [React Hot Loader](https://github.com/gaearon/react-hot-loader): Tweak react components in real time. -- [Vue Loader](https://github.com/vuejs/vue-loader): This loader supports HMR for vue components out of the box. -- [Elm Hot Loader](https://github.com/fluxxu/elm-hot-loader): Supports HMR for the Elm programming language. -- [Angular HMR](https://github.com/gdi2290/angular-hmr): No loader necessary! A simple change to your main NgModule file is all that's required to have full control over the HMR APIs. - -T> If you know of any other loaders or plugins that help with or enhance Hot Module Replacement please submit a pull request to add to this list! - - -# Tree Shaking - -_Tree shaking_ is a term commonly used in the JavaScript context for dead-code elimination. It relies on the [static structure](http://exploringjs.com/es6/ch_modules.html#static-module-structure) of ES2015 module syntax, i.e. [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export). The name and concept have been popularized by the ES2015 module bundler [rollup](https://github.com/rollup/rollup). - -The webpack 2 release came with built-in support for ES2015 modules (alias _harmony modules_) as well as unused module export detection. The new webpack 4 release expands on this capability with a way to provide hints to the compiler via the `"sideEffects"` `package.json` property to denote which files in your project are "pure" and therefore safe to prune if unused. - -T> The remainder of this guide will stem from [Getting Started](/guides/getting-started). If you haven't read through that guide already, please do so now. - - -## Add a Utility - -Let's add a new utility file to our project, `src/math.js`, that exports two functions: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist - |- bundle.js - |- index.html -|- /src - |- index.js -+ |- math.js -|- /node_modules -``` - -__src/math.js__ - -```javascript -export function square(x) { - return x * x; -} - -export function cube(x) { - return x * x * x; -} -``` - -Set the `mode` configuration option to [development](/concepts/mode/#mode-development) to make sure that the bundle is not minified: - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') -- } -+ }, -+ mode: 'development', -+ optimization: { -+ usedExports: true -+ } -}; -``` - -With that in place, let's update our entry script to utilize one of these new methods and remove `lodash` for simplicity: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -+ import { cube } from './math.js'; - - function component() { -- var element = document.createElement('div'); -+ var element = document.createElement('pre'); - -- // Lodash, now imported by this script -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.innerHTML = [ -+ 'Hello webpack!', -+ '5 cubed is equal to ' + cube(5) -+ ].join('\n\n'); - - return element; - } - - document.body.appendChild(component()); -``` - -Note that we __did not `import` the `square` method__ from the `src/math.js` module. That function is what's known as "dead code", meaning an unused `export` that should be dropped. Now let's run our npm script, `npm run build`, and inspect the output bundle: - -__dist/bundle.js (around lines 90 - 100)__ - -```js -/* 1 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - 'use strict'; - /* unused harmony export square */ - /* harmony export (immutable) */ __webpack_exports__['a'] = cube; - function square(x) { - return x * x; - } - - function cube(x) { - return x * x * x; - } -}); -``` - -Note the `unused harmony export square` comment above. If you look at the code below it, you'll notice that `square` is not being imported, however, it is still included in the bundle. We'll fix that in the next section. - - -## Mark the file as side-effect-free - -In a 100% ESM module world, identifying side effects is straightforward. However, we aren't there just yet, so in the mean time it's necessary to provide hints to webpack's compiler on the "pureness" of your code. - -The way this is accomplished is the `"sideEffects"` package.json property. - -```json -{ - "name": "your-project", - "sideEffects": false -} -``` - -All the code noted above does not contain side effects, so we can simply mark the property as `false` to inform webpack that it can safely prune unused exports. - -T> A "side effect" is defined as code that performs a special behavior when imported, other than exposing one or more exports. An example of this are polyfills, which affect the global scope and usually do not provide an export. - -If your code did have some side effects though, an array can be provided instead: - -```json -{ - "name": "your-project", - "sideEffects": [ - "./src/some-side-effectful-file.js" - ] -} -``` - -The array accepts relative, absolute, and glob patterns to the relevant files. It uses [micromatch](https://github.com/micromatch/micromatch#matching-features) under the hood. - -T> Note that any imported file is subject to tree shaking. This means if you use something like `css-loader` in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode: - -```json -{ - "name": "your-project", - "sideEffects": [ - "./src/some-side-effectful-file.js", - "*.css" - ] -} -``` - -Finally, `"sideEffects"` can also be set from the [`module.rules` configuration option](/configuration/module/#module-rules). - -## Minify the Output - -So we've cued up our "dead code" to be dropped by using the `import` and `export` syntax, but we still need to drop it from the bundle. To do that set the `mode` configuration option to [`production`](/concepts/mode/#mode-production) configuration option. - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- mode: 'development', -- optimization: { -- usedExports: true -- } -+ mode: 'production' -}; -``` - -T> Note that the `--optimize-minimize` flag can be used to enable `TerserPlugin` as well. - -With that squared away, we can run another `npm run build` and see if anything has changed. - -Notice anything different about `dist/bundle.js`? Clearly the whole bundle is now minified and mangled, but, if you look carefully, you won't see the `square` function included but will see a mangled version of the `cube` function (`function r(e){return e*e*e}n.a=r`). With minification and tree shaking our bundle is now a few bytes smaller! While that may not seem like much in this contrived example, tree shaking can yield a significant decrease in bundle size when working on larger applications with complex dependency trees. - -T> [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) is needed for the tree shaking to work. It is added by `mode: "production"`. If you are not using it, remember to add the [ModuleConcatenationPlugin](/plugins/module-concatenation-plugin) manually. - -## Conclusion - -So, what we've learned is that in order to take advantage of _tree shaking_, you must... - -- Use ES2015 module syntax (i.e. `import` and `export`). -- Ensure no compilers transform your ES2015 module syntax into CommonJS modules (this is the default behavior of popular Babel preset @babel/preset-env - see [documentation](https://babeljs.io/docs/en/babel-preset-env#modules) for more details). -- Add a `"sideEffects"` property to your project's `package.json` file. -- Use [`production`](/concepts/mode/#mode-production) `mode` configuration option to enable [various optimizations](/concepts/mode/#usage) including minification and tree shaking. - -You can imagine your application as a tree. The source code and libraries you actually use represent the green, living leaves of the tree. Dead code represents the brown, dead leaves of the tree that are consumed by autumn. In order to get rid of the dead leaves, you have to shake the tree, causing them to fall. - -If you are interested in more ways to optimize your output, please jump to the next guide for details on building for [production](/guides/production). - - -# Production - -In this guide we'll dive into some of the best practices and utilities for building a production site or application. - -T> This walkthrough stems from [Tree Shaking](/guides/tree-shaking) and [Development](/guides/development). Please ensure you are familiar with the concepts/setup introduced in those guides before continuing on. - - -## Setup - -The goals of _development_ and _production_ builds differ greatly. In _development_, we want strong source mapping and a localhost server with live reloading or hot module replacement. In _production_, our goals shift to a focus on minified bundles, lighter weight source maps, and optimized assets to improve load time. With this logical separation at hand, we typically recommend writing __separate webpack configurations__ for each environment. - -While we will separate the _production_ and _development_ specific bits out, note that we'll still maintain a "common" configuration to keep things DRY. In order to merge these configurations together, we'll use a utility called [`webpack-merge`](https://github.com/survivejs/webpack-merge). With the "common" configuration in place, we won't have to duplicate code within the environment-specific configurations. - -Let's start by installing `webpack-merge` and splitting out the bits we've already worked on in previous guides: - -``` bash -npm install --save-dev webpack-merge -``` - -__project__ - -``` diff - webpack-demo - |- package.json -- |- webpack.config.js -+ |- webpack.common.js -+ |- webpack.dev.js -+ |- webpack.prod.js - |- /dist - |- /src - |- index.js - |- math.js - |- /node_modules -``` - -__webpack.common.js__ - -``` diff -+ const path = require('path'); -+ const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const HtmlWebpackPlugin = require('html-webpack-plugin'); -+ -+ module.exports = { -+ entry: { -+ app: './src/index.js' -+ }, -+ plugins: [ -+ new CleanWebpackPlugin(['dist']), -+ new HtmlWebpackPlugin({ -+ title: 'Production' -+ }) -+ ], -+ output: { -+ filename: '[name].bundle.js', -+ path: path.resolve(__dirname, 'dist') -+ } -+ }; -``` - -__webpack.dev.js__ - -``` diff -+ const merge = require('webpack-merge'); -+ const common = require('./webpack.common.js'); -+ -+ module.exports = merge(common, { -+ mode: 'development', -+ devtool: 'inline-source-map', -+ devServer: { -+ contentBase: './dist' -+ } -+ }); -``` - -__webpack.prod.js__ - -``` diff -+ const merge = require('webpack-merge'); -+ const common = require('./webpack.common.js'); -+ -+ module.exports = merge(common, { -+ mode: 'production', -+ }); -``` - -In `webpack.common.js`, we now have setup our `entry` and `output` configuration and we've included any plugins that are required for both environments. In `webpack.dev.js`, we've set ``mode`` to ``development``. Also, we've added the recommended `devtool` for that environment (strong source mapping), as well as our simple `devServer` configuration. Finally, in `webpack.prod.js`,``mode`` is set to ``production`` which loads `TerserPlugin` which was first introduced by the [tree shaking](/guides/tree-shaking) guide. - -Note the use of `merge()` in the environment-specific configurations to easily include our common configuration in `dev` and `prod`. The `webpack-merge` tool offers a variety of advanced features for merging but for our use case we won't need any of that. - - -## NPM Scripts - -Now let's repoint our `scripts` to the new configurations. We'll use the _development_ one for our `webpack-dev-server`, `npm start`, script and the _production_ one for our `npm run build` script: - -__package.json__ - -``` diff - { - "name": "development", - "version": "1.0.0", - "description": "", - "main": "src/index.js", - "scripts": { -- "start": "webpack-dev-server --open", -+ "start": "webpack-dev-server --open --config webpack.dev.js", -- "build": "webpack" -+ "build": "webpack --config webpack.prod.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "clean-webpack-plugin": "^0.1.17", - "css-loader": "^0.28.4", - "csv-loader": "^2.1.1", - "express": "^4.15.3", - "file-loader": "^0.11.2", - "html-webpack-plugin": "^2.29.0", - "style-loader": "^0.18.2", - "webpack": "^3.0.0", - "webpack-dev-middleware": "^1.12.0", - "webpack-dev-server": "^2.9.1", - "webpack-merge": "^4.1.0", - "xml-loader": "^1.2.1" - } - } -``` - -Feel free to run those scripts and see how the output changes as we continue adding to our _production_ configuration. - - -## Specify the Mode - -Many libraries will key off the `process.env.NODE_ENV` variable to determine what should be included in the library. For example, when not in _production_ some libraries may add additional logging and testing to make debugging easier. However, with `process.env.NODE_ENV === 'production'` they might drop or add significant portions of code to optimize how things run for your actual users. Since webpack v4, specifying [`mode`](/concepts/mode/) automatically configures [`DefinePlugin`](/plugins/define-plugin) for you: - -__webpack.prod.js__ - -``` diff - const merge = require('webpack-merge'); - const common = require('./webpack.common.js'); - - module.exports = merge(common, { - mode: 'production', - }); -``` - -T> Technically, `NODE_ENV` is a system environment variable that Node.js exposes into running scripts. It is used by convention to determine dev-vs-prod behavior by server tools, build scripts, and client-side libraries. Contrary to expectations, `process.env.NODE_ENV` is not set to `"production"` __within__ the build script `webpack.config.js`, see [#2537](https://github.com/webpack/webpack/issues/2537). Thus, conditionals like `process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'` within webpack configurations do not work as expected. - -If you're using a library like [`react`](https://reactjs.org/), you should actually see a significant drop in bundle size after adding this plugin. Also note that any of our local `/src` code can key off of this as well, so the following check would be valid: - -__src/index.js__ - -``` diff - import { cube } from './math.js'; -+ -+ if (process.env.NODE_ENV !== 'production') { -+ console.log('Looks like we are in development mode!'); -+ } - - function component() { - var element = document.createElement('pre'); - - element.innerHTML = [ - 'Hello webpack!', - '5 cubed is equal to ' + cube(5) - ].join('\n\n'); - - return element; - } - - document.body.appendChild(component()); -``` - - -## Minification - -webpack v4+ will minify your code by default in [`production mode`](/concepts/mode/#mode-production). - -Note that while the [`TerserPlugin`](/plugins/terser-webpack-plugin) is a great place to start for minification and being used by default, there are other options out there. Here are a few more popular ones: - -- [`BabelMinifyWebpackPlugin`](https://github.com/webpack-contrib/babel-minify-webpack-plugin) -- [`ClosureCompilerPlugin`](https://github.com/roman01la/webpack-closure-compiler) - -If you decide to try another minification plugin, just make sure your new choice also drops dead code as described in the [tree shaking](/guides/tree-shaking) guide and provide it as the [`optimization.minimizer`](/configuration/optimization/#optimization-minimizer). - - -## Source Mapping - -We encourage you to have source maps enabled in production, as they are useful for debugging as well as running benchmark tests. That said, you should choose one with a fairly quick build speed that's recommended for production use (see [`devtool`](/configuration/devtool)). For this guide, we'll use the `source-map` option in _production_ as opposed to the `inline-source-map` we used in _development_: - -__webpack.prod.js__ - -``` diff - const merge = require('webpack-merge'); - const common = require('./webpack.common.js'); - - module.exports = merge(common, { - mode: 'production', -+ devtool: 'source-map' - }); -``` - -T> Avoid `inline-***` and `eval-***` use in production as they can increase bundle size and reduce the overall performance. - - -## Minimize CSS - -It is crucial to minimize your CSS on production, please see [Minimizing for Production](/plugins/mini-css-extract-plugin/#minimizing-for-production) section. - - -## CLI Alternatives - -Some of what has been described above is also achievable via the command line. For example, the `--optimize-minimize` flag will include the `TerserPlugin` behind the scenes. The `--define process.env.NODE_ENV="'production'"` will do the same for the `DefinePlugin` instance described above. And, `webpack -p` will automatically invoke both those flags and thus the plugins to be included. - -While these short hand methods are nice, we usually recommend just using the configuration as it's better to understand exactly what is being done for you in both cases. The configuration also gives you more control on fine tuning other options within both plugins. - - -# Code Splitting - -T> This guide extends the examples provided in [Getting Started](/guides/getting-started) and [Output Management](/guides/output-management). Please make sure you are at least familiar with the examples provided in them. - -Code splitting is one of the most compelling features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel. It can be used to achieve smaller bundles and control resource load prioritization which, if used correctly, can have a major impact on load time. - -There are three general approaches to code splitting available: - -- Entry Points: Manually split code using [`entry`](/configuration/entry-context) configuration. -- Prevent Duplication: Use the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) to dedupe and split chunks. -- Dynamic Imports: Split code via inline function calls within modules. - - -## Entry Points - -This is by far the easiest, and most intuitive, way to split code. However, it is more manual and has some pitfalls we will go over. Let's take a look at how we might split another module from the main bundle: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- another-module.js -|- /node_modules -``` - -__another-module.js__ - -``` js -import _ from 'lodash'; - -console.log( - _.join(['Another', 'module', 'loaded!'], ' ') -); -``` - -__webpack.config.js__ - -``` diff -const path = require('path'); - -module.exports = { - mode: 'development', - entry: { - index: './src/index.js', -+ another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -This will yield the following build result: - -``` bash -... - Asset Size Chunks Chunk Names -another.bundle.js 550 KiB another [emitted] another - index.bundle.js 550 KiB index [emitted] index -Entrypoint index = index.bundle.js -Entrypoint another = another.bundle.js -... -``` - -As mentioned there are some pitfalls to this approach: - -- If there are any duplicated modules between entry chunks they will be included in both bundles. -- It isn't as flexible and can't be used to dynamically split code with the core application logic. - -The first of these two points is definitely an issue for our example, as `lodash` is also imported within `./src/index.js` and will thus be duplicated in both bundles. Let's remove this duplication by using the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). - - -## Prevent Duplication - -The [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) allows us to extract common dependencies into an existing entry chunk or an entirely new chunk. Let's use this to de-duplicate the `lodash` dependency from the previous example: - -W> The `CommonsChunkPlugin` has been removed in webpack v4 legato. To learn how chunks are treated in the latest version, check out the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/). - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - mode: 'development', - entry: { - index: './src/index.js', - another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ optimization: { -+ splitChunks: { -+ chunks: 'all' -+ } -+ } - }; -``` - -With the [`optimization.splitChunks`](/plugins/split-chunks-plugin/#optimization-splitchunks) configuration option in place, we should now see the duplicate dependency removed from our `index.bundle.js` and `another.bundle.js`. The plugin should notice that we've separated `lodash` out to a separate chunk and remove the dead weight from our main bundle. Let's do an `npm run build` to see if it worked: - -``` bash -... - Asset Size Chunks Chunk Names - another.bundle.js 5.95 KiB another [emitted] another - index.bundle.js 5.89 KiB index [emitted] index -vendors~another~index.bundle.js 547 KiB vendors~another~index [emitted] vendors~another~index -Entrypoint index = vendors~another~index.bundle.js index.bundle.js -Entrypoint another = vendors~another~index.bundle.js another.bundle.js -... -``` - -Here are some other useful plugins and loaders provided by the community for splitting code: - -- [`mini-css-extract-plugin`](/plugins/mini-css-extract-plugin): Useful for splitting CSS out from the main application. -- [`bundle-loader`](/loaders/bundle-loader): Used to split code and lazy load the resulting bundles. -- [`promise-loader`](https://github.com/gaearon/promise-loader): Similar to the `bundle-loader` but uses promises. - - -## Dynamic Imports - -Two similar techniques are supported by webpack when it comes to dynamic code splitting. The first and recommended approach is to use the [`import()` syntax](/api/module-methods#import-) that conforms to the [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) for dynamic imports. The legacy, webpack-specific approach is to use [`require.ensure`](/api/module-methods#require-ensure). Let's try using the first of these two approaches... - -W> `import()` calls use [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). - -Before we start, let's remove the extra [`entry`](/concepts/entry-points/) and [`optimization.splitChunks`](/plugins/split-chunks-plugin) from our config as they won't be needed for this next demonstration: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - mode: 'development', - entry: { -+ index: './src/index.js' -- index: './src/index.js', -- another: './src/another-module.js' - }, - output: { - filename: '[name].bundle.js', -+ chunkFilename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, -- optimization: { -- splitChunks: { -- chunks: 'all' -- } -- } - }; -``` - -Note the use of `chunkFilename`, which determines the name of non-entry chunk files. For more information on `chunkFilename`, see [output documentation](/configuration/output/#output-chunkfilename). We'll also update our project to remove the now unused files: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -- |- another-module.js -|- /node_modules -``` - -Now, instead of statically importing `lodash`, we'll use dynamic importing to separate a chunk: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -- -- function component() { -+ function getComponent() { -- var element = document.createElement('div'); -- -- // Lodash, now imported by this script -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => { -+ var element = document.createElement('div'); -+ -+ element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ -+ return element; -+ -+ }).catch(error => 'An error occurred while loading the component'); - } - -- document.body.appendChild(component()); -+ getComponent().then(component => { -+ document.body.appendChild(component); -+ }) -``` - -The reason we need `default` is since webpack 4, when importing a CommonJS module, the import will no longer resolve to the value of `module.exports`, it will instead create an artificial namespace object for the CommonJS module, for more information on the reason behind this, read [webpack 4: import() and CommonJs](https://medium.com/webpack/webpack-4-import-and-commonjs-d619d626b655) - -Note the use of `webpackChunkName` in the comment. This will cause our separate bundle to be named `lodash.bundle.js` instead of just `[id].bundle.js`. For more information on `webpackChunkName` and the other available options, see the [`import()` documentation](/api/module-methods#import-). Let's run webpack to see `lodash` separated out to a separate bundle: - -``` bash -... - Asset Size Chunks Chunk Names - index.bundle.js 7.88 KiB index [emitted] index -vendors~lodash.bundle.js 547 KiB vendors~lodash [emitted] vendors~lodash -Entrypoint index = index.bundle.js -... -``` - -As `import()` returns a promise, it can be used with [`async` functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). However, this requires using a pre-processor like Babel and the [Syntax Dynamic Import Babel Plugin](https://babeljs.io/docs/plugins/syntax-dynamic-import/#installation). Here's how it would simplify the code: - -__src/index.js__ - -``` diff -- function getComponent() { -+ async function getComponent() { -- return import(/* webpackChunkName: "lodash" */ 'lodash').then({ default: _ } => { -- var element = document.createElement('div'); -- -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- -- return element; -- -- }).catch(error => 'An error occurred while loading the component'); -+ var element = document.createElement('div'); -+ const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash'); -+ -+ element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ -+ return element; - } - - getComponent().then(component => { - document.body.appendChild(component); - }); -``` - - -## Prefetching/Preloading modules - -webpack 4.6.0+ adds support for prefetching and preloading. - -Using these inline directives while declaring your imports allows webpack to output “Resource Hint” which tells the browser that for: - -- prefetch: resource is probably needed for some navigation in the future -- preload: resource might be needed during the current navigation - -Simple prefetch example can be having a `HomePage` component, which renders a `LoginButton` component which then on demand loads a `LoginModal` component after being clicked. - -__LoginButton.js__ - -```js -//... -import(/* webpackPrefetch: true */ 'LoginModal'); -``` - -This will result in `<link rel="prefetch" href="login-modal-chunk.js">` being appended in the head of the page, which will instruct the browser to prefetch in idle time the `login-modal-chunk.js` file. - -T> webpack will add the prefetch hint once the parent chunk has been loaded. - -Preload directive has a bunch of differences compared to prefetch: - -- A preloaded chunk starts loading in parallel to the parent chunk. A prefetched chunk starts after the parent chunk finishes loading. -- A preloaded chunk has medium priority and is instantly downloaded. A prefetched chunk is downloaded while browser is idle. -- A preloaded chunk should be instantly requested by the parent chunk. A prefetched chunk can be used anytime in the future. -- Browser support is different. - -Simple preload example can be having a `Component` which always depends on a big library that should be in a separate chunk. - -Let's imagine a component `ChartComponent` which needs huge `ChartingLibrary`. It displays a `LoadingIndicator` when rendered and instantly does an on demand import of `ChartingLibrary`: - -__ChartComponent.js__ - -```js -//... -import(/* webpackPreload: true */ 'ChartingLibrary'); -``` - -When a page which uses the `ChartComponent` is requested, the charting-library-chunk is also requested via `<link rel="preload">`. Assuming the page-chunk is smaller and finishes faster, the page will be displayed with a `LoadingIndicator`, until the already requested `charting-library-chunk` finishes. This will give a little load time boost since it only needs one round-trip instead of two. Especially in high-latency environments. - -T> Using webpackPreload incorrectly can actually hurt performance, so be careful when using it. - - -## Bundle Analysis - -Once you start splitting your code, it can be useful to analyze the output to check where modules have ended up. The [official analyze tool](https://github.com/webpack/analyse) is a good place to start. There are some other community-supported options out there as well: - -- [webpack-chart](https://alexkuz.github.io/webpack-chart/): Interactive pie chart for webpack stats. -- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/): Visualize and analyze your bundles to see which modules are taking up space and which might be duplicates. -- [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer): A plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap. -- [webpack bundle optimize helper](https://webpack.jakoblind.no/optimize): This tool will analyze your bundle and give you actionable suggestions on what to improve to reduce your bundle size. - -## Next Steps - -See [Lazy Loading](/guides/lazy-loading) for a more concrete example of how `import()` can be used in a real application and [Caching](/guides/caching) to learn how to split code more effectively. - - -# Lazy Loading - -T> This guide is a small follow-up to [Code Splitting](/guides/code-splitting). If you have not yet read through that guide, please do so now. - -Lazy, or "on demand", loading is a great way to optimize your site or application. This practice essentially involves splitting your code at logical breakpoints, and then loading it once the user has done something that requires, or will require, a new block of code. This speeds up the initial load of the application and lightens its overall weight as some blocks may never even be loaded. - - -## Example - -Let's take the example from [Code Splitting](/guides/code-splitting#dynamic-imports) and tweak it a bit to demonstrate this concept even more. The code there does cause a separate chunk, `lodash.bundle.js`, to be generated and technically "lazy-loads" it as soon as the script is run. The trouble is that no user interaction is required to load the bundle -- meaning that every time the page is loaded, the request will fire. This doesn't help us too much and will impact performance negatively. - -Let's try something different. We'll add an interaction to log some text to the console when the user clicks a button. However, we'll wait to load that code (`print.js`) until the interaction occurs for the first time. To do this we'll go back and rework the [final _Dynamic Imports_ example](/guides/code-splitting#dynamic-imports) from _Code Splitting_ and leave `lodash` in the main chunk. - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- print.js -|- /node_modules -``` - -__src/print.js__ - -``` js -console.log('The print.js module has loaded! See the network tab in dev tools...'); - -export default () => { - console.log('Button Clicked: Here\'s "some text"!'); -}; -``` - -__src/index.js__ - -``` diff -+ import _ from 'lodash'; -+ -- async function getComponent() { -+ function component() { - var element = document.createElement('div'); -- const _ = await import(/* webpackChunkName: "lodash" */ 'lodash'); -+ var button = document.createElement('button'); -+ var br = document.createElement('br'); - -+ button.innerHTML = 'Click me and look at the console!'; - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.appendChild(br); -+ element.appendChild(button); -+ -+ // Note that because a network request is involved, some indication -+ // of loading would need to be shown in a production-level site/app. -+ button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => { -+ var print = module.default; -+ -+ print(); -+ }); - - return element; - } - -- getComponent().then(component => { -- document.body.appendChild(component); -- }); -+ document.body.appendChild(component()); -``` - -W> Note that when using `import()` on ES6 modules you must reference the `.default` property as it's the actual `module` object that will be returned when the promise is resolved. - -Now let's run webpack and check out our new lazy-loading functionality: - -``` bash -... - Asset Size Chunks Chunk Names -print.bundle.js 417 bytes 0 [emitted] print -index.bundle.js 548 kB 1 [emitted] [big] index - index.html 189 bytes [emitted] -... -``` - - -## Frameworks - -Many frameworks and libraries have their own recommendations on how this should be accomplished within their methodologies. Here are a few examples: - -- React: [Code Splitting and Lazy Loading](https://reacttraining.com/react-router/web/guides/code-splitting) -- Vue: [Lazy Load in Vue using Webpack's code splitting](https://alexjoverm.github.io/2017/07/16/Lazy-load-in-Vue-using-Webpack-s-code-splitting/) -- AngularJS: [AngularJS + Webpack = lazyLoad](https://medium.com/@var_bin/angularjs-webpack-lazyload-bb7977f390dd) by [@var_bincom](https://twitter.com/var_bincom) - - -# Caching - -T> The examples in this guide stem from [getting started](/guides/getting-started), [output management](/guides/output-management) and [code splitting](/guides/code-splitting). - -So we're using webpack to bundle our modular application which yields a deployable `/dist` directory. Once the contents of `/dist` have been deployed to a server, clients (typically browsers) will hit that server to grab the site and its assets. The last step can be time consuming, which is why browsers use a technique called [caching](https://searchstorage.techtarget.com/definition/cache). This allows sites to load faster with less unnecessary network traffic, however it can also cause headaches when you need new code to be picked up. - -This guide focuses on the configuration needed to ensure files produced by webpack compilation can remain cached unless their contents has changed. - - -## Output Filenames - -A simple way to ensure the browser picks up changed files is by using `output.filename` [substitutions](/configuration/output#output-filename). The `[hash]` substitution can be used to include a build-specific hash in the filename, however it's even better to use the `[contenthash]` substitution which is the hash of the content of a file, which is different for each asset. - -Let's get our project set up using the example from [getting started](/guides/getting-started) with the `plugins` from [output management](/guides/output-management), so we don't have to deal with maintaining our `index.html` file manually: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -|- /node_modules -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ -- title: 'Output Management' -+ title: 'Caching' - }) - ], - output: { -- filename: 'bundle.js', -+ filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -Running our build script, `npm run build`, with this configuration should produce the following output: - -``` bash -... - Asset Size Chunks Chunk Names -main.7e2c49a622975ebd9b7e.js 544 kB 0 [emitted] [big] main - index.html 197 bytes [emitted] -... -``` - -As you can see the bundle's name now reflects its content (via the hash). If we run another build without making any changes, we'd expect that filename to stay the same. However, if we were to run it again, we may find that this is not the case: - -``` bash -... - Asset Size Chunks Chunk Names -main.205199ab45963f6a62ec.js 544 kB 0 [emitted] [big] main - index.html 197 bytes [emitted] -... -``` - -This is because webpack includes certain boilerplate, specifically the runtime and manifest, in the entry chunk. - -W> Output may differ depending on your current webpack version. Newer versions may not have all the same issues with hashing as some older versions, but we still recommend the following steps to be safe. - -## Extracting Boilerplate - -As we learned in [code splitting](/guides/code-splitting), the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) can be used to split modules out into separate bundles. webpack provides an optimization feature which does split out runtime code into a separate chunk(s) according to the options provided, simply use [`optimization.runtimeChunk`](/configuration/optimization/#optimization-runtimechunk) set to `single` for creating one runtime bundle: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, -+ optimization: { -+ runtimeChunk: 'single' -+ } - }; -``` - -Let's run another build to see the extracted `runtime` bundle: - -``` bash -Hash: 82c9c385607b2150fab2 -Version: webpack 4.12.0 -Time: 3027ms - Asset Size Chunks Chunk Names -runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime - main.e81de2cf758ada72f306.js 69.5 KiB 1 [emitted] main - index.html 275 bytes [emitted] -[1] (webpack)/buildin/module.js 497 bytes {1} [built] -[2] (webpack)/buildin/global.js 489 bytes {1} [built] -[3] ./src/index.js 309 bytes {1} [built] - + 1 hidden module -``` - -It's also good practice to extract third-party libraries, such as `lodash` or `react`, to a separate `vendor` chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date. -This can be done by using the [`cacheGroups`](/plugins/split-chunks-plugin/#splitchunks-cachegroups) option of the [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) demonstrated in [Example 2 of SplitChunksPlugin](/plugins/split-chunks-plugin/#split-chunks-example-2). Lets add `optimization.splitChunks` with `cacheGroups` with next params and build: - -__webpack.config.js__ - -``` diff - var path = require('path'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - }), - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, - optimization: { -- runtimeChunk: 'single' -+ runtimeChunk: 'single', -+ splitChunks: { -+ cacheGroups: { -+ vendor: { -+ test: /[\\/]node_modules[\\/]/, -+ name: 'vendors', -+ chunks: 'all' -+ } -+ } -+ } - } - }; -``` - -Let's run another build to see our new `vendor` bundle: - -``` bash -... - Asset Size Chunks Chunk Names -runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime -vendors.a42c3ca0d742766d7a28.js 69.4 KiB 1 [emitted] vendors - main.abf44fedb7d11d4312d7.js 240 bytes 2 [emitted] main - index.html 353 bytes [emitted] -... -``` - -We can now see that our `main` bundle does not contain `vendor` code from `node_modules` directory and is down in size to `240 bytes`! - -## Module Identifiers - -Let's add another module, `print.js`, to our project: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -+ |- print.js -|- /node_modules -``` - -__print.js__ - -``` diff -+ export default function print(text) { -+ console.log(text); -+ }; -``` - -__src/index.js__ - -``` diff - import _ from 'lodash'; -+ import Print from './print'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.onclick = Print.bind(null, 'Hello webpack!'); - - return element; - } - - document.body.appendChild(component()); -``` - -Running another build, we would expect only our `main` bundle's hash to change, however... - -``` bash -... - Asset Size Chunks Chunk Names - vendor.a7561fb0e9a071baadb9.js 541 kB 0 [emitted] [big] vendor - main.b746e3eb72875af2caa9.js 1.22 kB 1 [emitted] main -manifest.1400d5af64fc1b7b3a45.js 5.85 kB 2 [emitted] manifest - index.html 352 bytes [emitted] -... -``` - -... we can see that all three have. This is because each [`module.id`](/api/module-variables#module-id-commonjs-) is incremented based on resolving order by default. Meaning when the order of resolving is changed, the IDs will be changed as well. So, to recap: - -- The `main` bundle changed because of its new content. -- The `vendor` bundle changed because its `module.id` was changed. -- And, the `manifest` bundle changed because it now contains a reference to a new module. - -The first and last are expected -- it's the `vendor` hash we want to fix. Luckily, there are two plugins we can use to resolve this issue. The first is the `NamedModulesPlugin`, which will use the path to the module rather than a numerical identifier. While this plugin is useful during development for more readable output, it does take a bit longer to run. The second option is the [`HashedModuleIdsPlugin`](/plugins/hashed-module-ids-plugin), which is recommended for production builds: - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const webpack = require('webpack'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - - module.exports = { - entry: './src/index.js', - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ - title: 'Caching' - }), -+ new webpack.HashedModuleIdsPlugin() - ], - output: { - filename: '[name].[contenthash].js', - path: path.resolve(__dirname, 'dist') - }, - optimization: { - runtimeChunk: 'single', - splitChunks: { - cacheGroups: { - vendor: { - test: /[\\/]node_modules[\\/]/, - name: 'vendors', - chunks: 'all' - } - } - } - } - }; -``` - -Now, despite any new local dependencies, our `vendor` hash should stay consistent between builds: - -``` bash -... - Asset Size Chunks Chunk Names - main.216e852f60c8829c2289.js 340 bytes 0 [emitted] main -vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors -runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime - index.html 353 bytes [emitted] -Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.216e852f60c8829c2289.js -... -``` - -And let's modify our `src/index.js` to temporarily remove that extra dependency: - -__src/index.js__ - -``` diff - import _ from 'lodash'; -- import Print from './print'; -+ // import Print from './print'; - - function component() { - var element = document.createElement('div'); - - // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); -- element.onclick = Print.bind(null, 'Hello webpack!'); -+ // element.onclick = Print.bind(null, 'Hello webpack!'); - - return element; - } - - document.body.appendChild(component()); -``` - -And finally run our build again: - -``` bash -... - Asset Size Chunks Chunk Names - main.ad717f2466ce655fff5c.js 274 bytes 0 [emitted] main -vendors.55e79e5927a639d21a1b.js 69.5 KiB 1 [emitted] vendors -runtime.725a1a51ede5ae0cfde0.js 1.42 KiB 2 [emitted] runtime - index.html 353 bytes [emitted] -Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.js main.ad717f2466ce655fff5c.js -... -``` - -We can see that both builds yielded `55e79e5927a639d21a1b` in the `vendor` bundle's filename. - - -## Conclusion - -Caching gets messy. Plain and simple. However the walk-through above should give you a running start to deploying consistent, cacheable assets. See the _Further Reading_ section below to learn more. - - -# Authoring Libraries - -Aside from applications, webpack can also be used to bundle JavaScript libraries. The following guide is meant for library authors looking to streamline their bundling strategy. - - -## Authoring a Library - -Let's assume that you are writing a small library ,`webpack-numbers`, that allows users to convert the numbers 1 through 5 from their numeric representation to a textual one and vice-versa, e.g. 2 to 'two'. - -The basic project structure may look like this: - -__project__ - -``` diff -+ |- webpack.config.js -+ |- package.json -+ |- /src -+ |- index.js -+ |- ref.json -``` - -Initialize npm, install webpack and lodash: - -``` bash -npm init -y -npm install --save-dev webpack lodash -``` - -__src/ref.json__ - -```json -[ - { - "num": 1, - "word": "One" - }, - { - "num": 2, - "word": "Two" - }, - { - "num": 3, - "word": "Three" - }, - { - "num": 4, - "word": "Four" - }, - { - "num": 5, - "word": "Five" - }, - { - "num": 0, - "word": "Zero" - } -] -``` - -__src/index.js__ - -``` js -import _ from 'lodash'; -import numRef from './ref.json'; - -export function numToWord(num) { - return _.reduce(numRef, (accum, ref) => { - return ref.num === num ? ref.word : accum; - }, ''); -} - -export function wordToNum(word) { - return _.reduce(numRef, (accum, ref) => { - return ref.word === word && word.toLowerCase() ? ref.num : accum; - }, -1); -} -``` - -The usage specification for the library use will be as follows: - -- __ES2015 module import:__ - -``` js -import * as webpackNumbers from 'webpack-numbers'; -// ... -webpackNumbers.wordToNum('Two'); -``` - -- __CommonJS module require:__ - -``` js -var webpackNumbers = require('webpack-numbers'); -// ... -webpackNumbers.wordToNum('Two'); -``` - -- __AMD module require:__ - -``` js -require(['webpackNumbers'], function ( webpackNumbers) { - // ... - webpackNumbers.wordToNum('Two'); -}); -``` - -The consumer also can use the library by loading it via a script tag: - -``` html -<!doctype html> -<html> - ... - <script src="https://unpkg.com/webpack-numbers"></script> - <script> - // ... - // Global variable - webpackNumbers.wordToNum('Five') - // Property in the window object - window.webpackNumbers.wordToNum('Five') - // ... - </script> -</html> -``` - -Note that we can also configure it to expose the library in the following ways: - -- Property in the global object, for node. -- Property in the `this` object. - -For full library configuration and code please refer to [webpack-library-example](https://github.com/kalcifer/webpack-library-example). - - -## Base Configuration - -Now let's bundle this library in a way that will achieve the following goals: - -- Using `externals` to avoid bundling `lodash`, so the consumer is required to load it. -- Setting the library name as `webpack-numbers`. -- Exposing the library as a variable called `webpackNumbers`. -- Being able to access the library inside Node.js. - -Also, the consumer should be able to access the library the following ways: - -- ES2015 module. i.e. `import webpackNumbers from 'webpack-numbers'`. -- CommonJS module. i.e. `require('webpack-numbers')`. -- Global variable when included through `script` tag. - -We can start with this basic webpack configuration: - -__webpack.config.js__ - -``` js -var path = require('path'); - -module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js' - } -}; -``` - - -## Externalize Lodash - -Now, if you run `webpack`, you will find that a largish bundle is created. If you inspect the file, you'll see that lodash has been bundled along with your code. In this case, we'd prefer to treat `lodash` as a `peerDependency`. Meaning that the consumer should already have `lodash` installed. Hence you would want to give up control of this external library to the consumer of your library. - -This can be done using the `externals` configuration: - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js' -- } -+ }, -+ externals: { -+ lodash: { -+ commonjs: 'lodash', -+ commonjs2: 'lodash', -+ amd: 'lodash', -+ root: '_' -+ } -+ } - }; -``` - -This means that your library expects a dependency named `lodash` to be available in the consumer's environment. - -T> Note that if you only plan on using your library as a dependency in another webpack bundle, you may specify `externals` as an array. - - -## External Limitations - -For libraries that use several files from a dependency: - -``` js -import A from 'library/one'; -import B from 'library/two'; - -// ... -``` - -You won't be able to exclude them from bundle by specifying `library` in the externals. You'll either need to exclude them one by one or by using a regular expression. - -``` js -module.exports = { - //... - externals: [ - 'library/one', - 'library/two', - // Everything that starts with "library/" - /^library\/.+$/ - ] -}; -``` - - -## Expose the Library - -For widespread use of the library, we would like it to be compatible in different environments, i.e. CommonJS, AMD, Node.js and as a global variable. To make your library available for consumption, add the `library` property inside `output`: - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), -- filename: 'webpack-numbers.js' -+ filename: 'webpack-numbers.js', -+ library: 'webpackNumbers' - }, - externals: { - lodash: { - commonjs: 'lodash', - commonjs2: 'lodash', - amd: 'lodash', - root: '_' - } - } - }; -``` - -T> Note that the `library` setup is tied to the `entry` configuration. For most libraries, specifying a single entry point is sufficient. While [multi-part libraries](https://github.com/webpack/webpack/tree/master/examples/multi-part-library) are possible, it is simpler to expose partial exports through an [index script](https://stackoverflow.com/questions/34072598/es6-exporting-importing-in-index-file) that serves as a single entry point. Using an `array` as an `entry` point for a library is __not recommended__. - -This exposes your library bundle available as a global variable named `webpackNumbers` when imported. To make the library compatible with other environments, add `libraryTarget` property to the config. This will add the different options about how the library can be exposed. - -__webpack.config.js__ - -``` diff - var path = require('path'); - - module.exports = { - entry: './src/index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'webpack-numbers.js', -- library: 'webpackNumbers' -+ library: 'webpackNumbers', -+ libraryTarget: 'umd' - }, - externals: { - lodash: { - commonjs: 'lodash', - commonjs2: 'lodash', - amd: 'lodash', - root: '_' - } - } - }; -``` - -You can expose the library in the following ways: - -- Variable: as a global variable made available by a `script` tag (`libraryTarget:'var'`). -- This: available through the `this` object (`libraryTarget:'this'`). -- Window: available trough the `window` object, in the browser (`libraryTarget:'window'`). -- UMD: available after AMD or CommonJS `require` (`libraryTarget:'umd'`). - -If `library` is set and `libraryTarget` is not, `libraryTarget` defaults to `var` as specified in the [output configuration documentation](/configuration/output). See [`output.libraryTarget`](/configuration/output#output-librarytarget) there for a detailed list of all available options. - -W> With webpack 3.5.5, using `libraryTarget: { root:'_' }` doesn't work properly (as stated in [issue 4824](https://github.com/webpack/webpack/issues/4824)). However, you can set `libraryTarget: { var: '_' }` to expect the library as a global variable. - - -### Final Steps - -Optimize your output for production by following the steps in the [production guide](/guides/production). Let's also add the path to your generated bundle as the package's `main` field in with our `package.json` - -__package.json__ - -``` json -{ - ... - "main": "dist/webpack-numbers.js", - ... -} -``` - -Or, to add as standard module as per [this guide](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage): - -``` json -{ - ... - "module": "src/index.js", - ... -} -``` - -The key `main` refers to the [standard from `package.json`](https://docs.npmjs.com/files/package.json#main), and `module` to [a](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md) [proposal](https://github.com/rollup/rollup/wiki/pkg.module) to allow the JavaScript ecosystem upgrade to use ES2015 modules without breaking backwards compatibility. - -W> The `module` property should point to a script that utilizes ES2015 module syntax but no other syntax features that aren't yet supported by browsers or node. This enables webpack to parse the module syntax itself, allowing for lighter bundles via [tree shaking](https://webpack.js.org/guides/tree-shaking/) if users are only consuming certain parts of the library. - -Now you can [publish it as an npm package](https://docs.npmjs.com/getting-started/publishing-npm-packages) and find it at [unpkg.com](https://unpkg.com/#/) to distribute it to your users. - -T> To expose stylesheets associated with your library, the [`ExtractTextPlugin`](/plugins/extract-text-webpack-plugin) should be used. Users can then consume and load these as they would any other stylesheet. - - -# Shimming - -The `webpack` compiler can understand modules written as ES2015 modules, CommonJS or AMD. However, some third party libraries may expect global dependencies (e.g. `$` for `jQuery`). The libraries might also create globals which need to be exported. These "broken modules" are one instance where _shimming_ comes into play. - -W> __We don't recommend using globals!__ The whole concept behind webpack is to allow more modular front-end development. This means writing isolated modules that are well contained and do not rely on hidden dependencies (e.g. globals). Please use these features only when necessary. - -Another instance where _shimming_ can be useful is when you want to [polyfill](https://en.wikipedia.org/wiki/Polyfill) browser functionality to support more users. In this case, you may only want to deliver those polyfills to the browsers that need patching (i.e. load them on demand). - -The following article will walk through both of these use cases. - -T> For simplicity, this guide stems from the examples in [Getting Started](/guides/getting-started). Please make sure you are familiar with the setup there before moving on. - - -## Shimming Globals - -Let's start with the first use case of shimming global variables. Before we do anything let's take another look at our project: - -__project__ - -``` diff -webpack-demo -|- package.json -|- webpack.config.js -|- /dist -|- /src - |- index.js -|- /node_modules -``` - -Remember that `lodash` package we were using? For demonstration purposes, let's say we wanted to instead provide this as a global throughout our application. To do this, we can use the `ProvidePlugin`. - -The [`ProvidePlugin`](/plugins/provide-plugin) makes a package available as a variable in every module compiled through webpack. If webpack sees that variable used, it will include the given package in the final bundle. Let's go ahead by removing the `import` statement for `lodash` and instead providing it via the plugin: - -__src/index.js__ - -``` diff -- import _ from 'lodash'; -- - function component() { - var element = document.createElement('div'); - -- // Lodash, now imported by this script - element.innerHTML = _.join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); -+ const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') -- } -+ }, -+ plugins: [ -+ new webpack.ProvidePlugin({ -+ _: 'lodash' -+ }) -+ ] - }; -``` - -What we've essentially done here is tell webpack... - -> If you encounter at least one instance of the variable `_`, include the `lodash` package and provide it to the modules that need it. - -If we run a build, we should still see the same output: - -``` bash -... - Asset Size Chunks Chunk Names -bundle.js 544 kB 0 [emitted] [big] main -... -``` - -We can also use the `ProvidePlugin` to expose a single export of a module by configuring it with an "array path" (e.g. `[module, child, ...children?]`). So let's imagine we only wanted to provide the `join` method from `lodash` wherever it's invoked: - -__src/index.js__ - -``` diff - function component() { - var element = document.createElement('div'); - -- element.innerHTML = _.join(['Hello', 'webpack'], ' '); -+ element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - plugins: [ - new webpack.ProvidePlugin({ -- _: 'lodash' -+ join: ['lodash', 'join'] - }) - ] - }; -``` - -This would go nicely with [Tree Shaking](/guides/tree-shaking) as the rest of the `lodash` library should get dropped. - - -## Granular Shimming - -Some legacy modules rely on `this` being the `window` object. Let's update our `index.js` so this is the case: - -``` diff - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); -+ -+ // Assume we are in the context of `window` -+ this.alert('Hmmm, this probably isn\'t a great idea...') - - return element; - } - - document.body.appendChild(component()); -``` - -This becomes a problem when the module is executed in a CommonJS context where `this` is equal to `module.exports`. In this case you can override `this` using the [`imports-loader`](/loaders/imports-loader/): - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, -+ module: { -+ rules: [ -+ { -+ test: require.resolve('index.js'), -+ use: 'imports-loader?this=>window' -+ } -+ ] -+ }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - - -## Global Exports - -Let's say a library creates a global variable that it expects its consumers to use. We can add a small module to our setup to demonstrate this: - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js -+ |- globals.js - |- /node_modules -``` - -__src/globals.js__ - -``` js -var file = 'blah.txt'; -var helpers = { - test: function() { console.log('test something'); }, - parse: function() { console.log('parse something'); } -}; -``` - -Now, while you'd likely never do this in your own source code, you may encounter a dated library you'd like to use that contains similar code to what's shown above. In this case, we can use [`exports-loader`](/loaders/exports-loader/), to export that global variable as a normal module export. For instance, in order to export `file` as `file` and `helpers.parse` as `parse`: - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: require.resolve('index.js'), - use: 'imports-loader?this=>window' -- } -+ }, -+ { -+ test: require.resolve('globals.js'), -+ use: 'exports-loader?file,parse=helpers.parse' -+ } - ] - }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - -Now from within our entry script (i.e. `src/index.js`), we could `import { file, parse } from './globals.js';` and all should work smoothly. - - -## Loading Polyfills - -Almost everything we've discussed thus far has been in relation to handling legacy packages. Let's move on to our second topic: __polyfills__. - -There's a lot of ways to load polyfills. For example, to include the [`babel-polyfill`](https://babeljs.io/docs/usage/polyfill/) we might simply: - -``` bash -npm install --save babel-polyfill -``` - -and `import` it so as to include it in our main bundle: - -__src/index.js__ - -``` diff -+ import 'babel-polyfill'; -+ - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -T> Note that we aren't binding the `import` to a variable. This is because polyfills simply run on their own, prior to the rest of the code base, allowing us to then assume certain native functionality exists. - -Now while this is one approach, __including polyfills in the main bundle is not recommended__ because this penalizes modern browsers users by making them download a bigger file with unneeded scripts. - -Let's move our `import` to a new file and add the [`whatwg-fetch`](https://github.com/github/fetch) polyfill: - -``` bash -npm install --save whatwg-fetch -``` - -__src/index.js__ - -``` diff -- import 'babel-polyfill'; -- - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -``` - -__project__ - -``` diff - webpack-demo - |- package.json - |- webpack.config.js - |- /dist - |- /src - |- index.js - |- globals.js -+ |- polyfills.js - |- /node_modules -``` - -__src/polyfills.js__ - -```javascript -import 'babel-polyfill'; -import 'whatwg-fetch'; -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const webpack = require('webpack'); - - module.exports = { -- entry: './src/index.js', -+ entry: { -+ polyfills: './src/polyfills.js', -+ index: './src/index.js' -+ }, - output: { -- filename: 'bundle.js', -+ filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - }, - module: { - rules: [ - { - test: require.resolve('index.js'), - use: 'imports-loader?this=>window' - }, - { - test: require.resolve('globals.js'), - use: 'exports-loader?file,parse=helpers.parse' - } - ] - }, - plugins: [ - new webpack.ProvidePlugin({ - join: ['lodash', 'join'] - }) - ] - }; -``` - -With that in place, we can add the logic to conditionally load our new `polyfills.bundle.js` file. How you make this decision depends on the technologies and browsers you need to support. We'll just do some simple testing to determine whether our polyfills are needed: - -__dist/index.html__ - -``` diff - <!doctype html> - <html> - <head> - <title>Getting Started</title> -+ <script> -+ var modernBrowser = ( -+ 'fetch' in window && -+ 'assign' in Object -+ ); -+ -+ if ( !modernBrowser ) { -+ var scriptElement = document.createElement('script'); -+ -+ scriptElement.async = false; -+ scriptElement.src = '/polyfills.bundle.js'; -+ document.head.appendChild(scriptElement); -+ } -+ </script> - </head> - <body> - <script src="index.bundle.js"></script> - </body> - </html> -``` - -Now we can `fetch` some data within our entry script: - -__src/index.js__ - -``` diff - function component() { - var element = document.createElement('div'); - - element.innerHTML = join(['Hello', 'webpack'], ' '); - - return element; - } - - document.body.appendChild(component()); -+ -+ fetch('https://jsonplaceholder.typicode.com/users') -+ .then(response => response.json()) -+ .then(json => { -+ console.log('We retrieved some data! AND we\'re confident it will work on a variety of browser distributions.') -+ console.log(json) -+ }) -+ .catch(error => console.error('Something went wrong when fetching this data: ', error)) -``` - -If we run our build, another `polyfills.bundle.js` file will be emitted and everything should still run smoothly in the browser. Note that this set up could likely be improved upon but it should give you a good idea of how you can provide polyfills only to the users that actually need them. - - -## Further Optimizations - -The `babel-preset-env` package uses [browserslist](https://github.com/browserslist/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the [`useBuiltIns`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins) option, `false` by default, which converts your global `babel-polyfill` import to a more granular feature by feature `import` pattern: - -``` js -import 'core-js/modules/es7.string.pad-start'; -import 'core-js/modules/es7.string.pad-end'; -import 'core-js/modules/web.timers'; -import 'core-js/modules/web.immediate'; -import 'core-js/modules/web.dom.iterable'; -``` - -See [the repository](https://github.com/babel/babel-preset-env) for more information. - - -## Node Built-Ins - -Node built-ins, like `process`, can be polyfilled right directly from your configuration file without the use of any special loaders or plugins. See the [node configuration page](/configuration/node) for more information and examples. - - -## Other Utilities - -There are a few other tools that can help when dealing with legacy modules. - -The [`script-loader`](/loaders/script-loader/) evaluates code in the global context, similar to inclusion via a `script` tag. In this mode, every normal library should work. `require`, `module`, etc. are undefined. - -W> When using the `script-loader`, the module is added as a string to the bundle. It is not minimized by `webpack`, so use a minimized version. There is also no `devtool` support for libraries added by this loader. - -When there is no AMD/CommonJS version of the module and you want to include the `dist`, you can flag this module in [`noParse`](/configuration/module/#module-noparse). This will cause webpack to include the module without parsing it or resolving `require()` and `import` statements. This practice is also used to improve the build performance. - -W> Any feature requiring the AST, like the `ProvidePlugin`, will not work. - -Lastly, there are some modules that support multiple [module styles](/concepts/modules); e.g. a combination of AMD, CommonJS, and legacy. In most of these cases, they first check for `define` and then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by setting `define=>false` via the [`imports-loader`](/loaders/imports-loader/). - - -# Progressive Web Application - -T> This guide extends on code examples found in the [Output Management](/guides/output-management) guide. - -Progressive Web Applications (or PWAs) are web apps that deliver an experience similar to native applications. There are many things that can contribute to that. Of these, the most significant is the ability for an app to be able to function when __offline__. This is achieved through the use of a web technology called [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers/). - -This section will focus on adding an offline experience to our app. We'll achieve this using a Google project called [Workbox](https://github.com/GoogleChrome/workbox) which provides tools that help make offline support for web apps easier to setup. - - -## We Don't Work Offline Now - -So far, we've been viewing the output by going directly to the local file system. Typically though, a real user accesses a web app over a network; their browser talking to a __server__ which will serve up the required assets (e.g. `.html`, `.js`, and `.css` files). - -So let's test what the current experience is like using a simple server. Let's use the [http-server](https://www.npmjs.com/package/http-server) package: `npm install http-server --save-dev`. We'll also amend the `scripts` section of our `package.json` to add in a `start` script: - -__package.json__ - -``` diff -{ - ... - "scripts": { -- "build": "webpack" -+ "build": "webpack", -+ "start": "http-server dist" - }, - ... -} -``` - -If you haven't previously done so, run the command `npm run build` to build your project. Then run the command `npm start`. This should produce the following output: - -``` bash -> http-server dist - -Starting up http-server, serving dist -Available on: - http://xx.x.x.x:8080 - http://127.0.0.1:8080 - http://xxx.xxx.x.x:8080 -Hit CTRL-C to stop the server -``` - -If you open your browser to `http://localhost:8080` (i.e. `http://127.0.0.1`) you should see your webpack application being served from the `dist` directory. If you stop the server and refresh, the webpack application is no longer available. - -This is what we aim to change. Once we reach the end of this module we should be able to stop the server, hit refresh and still see our application. - - -## Adding Workbox - -Let's add the Workbox webpack plugin and adjust the `webpack.config.js` file: - -``` bash -npm install workbox-webpack-plugin --save-dev -``` - -__webpack.config.js__ - -``` diff - const path = require('path'); - const HtmlWebpackPlugin = require('html-webpack-plugin'); - const CleanWebpackPlugin = require('clean-webpack-plugin'); -+ const WorkboxPlugin = require('workbox-webpack-plugin'); - - module.exports = { - entry: { - app: './src/index.js', - print: './src/print.js' - }, - plugins: [ - new CleanWebpackPlugin(['dist']), - new HtmlWebpackPlugin({ -- title: 'Output Management' -+ title: 'Progressive Web Application' -- }) -+ }), -+ new WorkboxPlugin.GenerateSW({ -+ // these options encourage the ServiceWorkers to get in there fast -+ // and not allow any straggling "old" SWs to hang around -+ clientsClaim: true, -+ skipWaiting: true -+ }) - ], - output: { - filename: '[name].bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -With that in place, let's see what happens when we do an `npm run build`: - -``` bash -... - Asset Size Chunks Chunk Names - app.bundle.js 545 kB 0, 1 [emitted] [big] app - print.bundle.js 2.74 kB 1 [emitted] print - index.html 254 bytes [emitted] -precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 268 bytes [emitted] - service-worker.js 1 kB [emitted] -... -``` - -As you can see, we now have 2 extra files being generated; `service-worker.js` and the more verbose `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js`. `service-worker.js` is the Service Worker file and `precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js` is a file that `service-worker.js` requires so it can run. Your own generated files will likely be different; but you should have an `service-worker.js` file there. - -So we're now at the happy point of having produced a Service Worker. What's next? - - -## Registering Our Service Worker - -Let's allow our Service Worker to come out and play by registering it. We'll do that by adding the registration code below: - -__index.js__ - -``` diff - import _ from 'lodash'; - import printMe from './print.js'; - -+ if ('serviceWorker' in navigator) { -+ window.addEventListener('load', () => { -+ navigator.serviceWorker.register('/service-worker.js').then(registration => { -+ console.log('SW registered: ', registration); -+ }).catch(registrationError => { -+ console.log('SW registration failed: ', registrationError); -+ }); -+ }); -+ } -``` - -Once more `npm run build` to build a version of the app including the registration code. Then serve it with `npm start`. Navigate to `http://localhost:8080` and take a look at the console. Somewhere in there you should see: - -``` bash -SW registered -``` - -Now to test it. Stop your server and refresh your page. If your browser supports Service Workers then you should still be looking at your application. However, it has been served up by your Service Worker and __not__ by the server. - - -## Conclusion - -You have built an offline app using the Workbox project. You've started the journey of turning your web app into a PWA. You may now want to think about taking things further. A good resource to help you with that can be found [here](https://developers.google.com/web/progressive-web-apps/). - - -# TypeScript - -T> This guide stems from the [_Getting Started_](/guides/getting-started/) guide. - -[TypeScript](https://www.typescriptlang.org) is a typed superset of JavaScript that compiles to plain JavaScript. In this guide we will learn how to integrate TypeScript with webpack. - - -## Basic Setup - -First install the TypeScript compiler and loader by running: - -``` bash -npm install --save-dev typescript ts-loader -``` - -Now we'll modify the directory structure & the configuration files: - -__project__ - -``` diff - webpack-demo - |- package.json -+ |- tsconfig.json - |- webpack.config.js - |- /dist - |- bundle.js - |- index.html - |- /src - |- index.js -+ |- index.ts - |- /node_modules -``` - -__tsconfig.json__ - -Let's set up a simple configuration to support JSX and compile TypeScript down to ES5... - -``` json -{ - "compilerOptions": { - "outDir": "./dist/", - "noImplicitAny": true, - "module": "es6", - "target": "es5", - "jsx": "react", - "allowJs": true - } -} -``` - -See [TypeScript's documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) to learn more about `tsconfig.json` configuration options. - -To learn more about webpack configuration, see the [configuration concepts](/concepts/configuration/). - -Now let's configure webpack to handle TypeScript: - -__webpack.config.js__ - -``` js -const path = require('path'); - -module.exports = { - entry: './src/index.ts', - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: [ '.tsx', '.ts', '.js' ] - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } -}; -``` - -This will direct webpack to _enter_ through `./index.ts`, _load_ all `.ts` and `.tsx` files through the `ts-loader`, and _output_ a `bundle.js` file in our current directory. - - -## Loader - -[`ts-loader`](https://github.com/TypeStrong/ts-loader) - -We use `ts-loader` in this guide as it makes enabling additional webpack features, such as importing other web assets, a bit easier. - - -## Source Maps - -To learn more about source maps, see the [development guide](/guides/development). - -To enable source maps, we must configure TypeScript to output inline source maps to our compiled JavaScript files. The following line must be added to our TypeScript configuration: - -__tsconfig.json__ - -``` diff - { - "compilerOptions": { - "outDir": "./dist/", -+ "sourceMap": true, - "noImplicitAny": true, - "module": "commonjs", - "target": "es5", - "jsx": "react", - "allowJs": true - } - } -``` - -Now we need to tell webpack to extract these source maps and include in our final bundle: - -__webpack.config.js__ - -``` diff - const path = require('path'); - - module.exports = { - entry: './src/index.ts', -+ devtool: 'inline-source-map', - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: [ '.tsx', '.ts', '.js' ] - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -``` - -See the [devtool documentation](/configuration/devtool/) for more information. - - -## Using Third Party Libraries - -When installing third party libraries from npm, it is important to remember to install the typing definition for that library. These definitions can be found at [TypeSearch](http://microsoft.github.io/TypeSearch/). - -For example if we want to install lodash we can run the following command to get the typings for it: - -``` bash -npm install --save-dev @types/lodash -``` - -For more information see [this blog post](https://blogs.msdn.microsoft.com/typescript/2016/06/15/the-future-of-declaration-files/). - - -## Importing Other Assets - -To use non-code assets with TypeScript, we need to defer the type for these imports. This requires a `custom.d.ts` file which signifies custom definitions for TypeScript in our project. Let's set up a declaration for `.svg` files: - -__custom.d.ts__ - -```typescript -declare module "*.svg" { - const content: any; - export default content; -} -``` - -Here we declare a new module for SVGs by specifying any import that ends in `.svg` and defining the module's `content` as `any`. We could be more explicit about it being a url by defining the type as string. The same concept applies to other assets including CSS, SCSS, JSON and more. - - -## Build Performance - -W> This may degrade build performance. - -See the [Build Performance](/guides/build-performance/) guide on build tooling. - - -# Environment Variables - -To disambiguate in your `webpack.config.js` between [development](/guides/development) and [production builds](/guides/production) you may use environment variables. - -The webpack command line [environment option](/api/cli/#environment-options) `--env` allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your `webpack.config.js`. For example, `--env.production` or `--env.NODE_ENV=local` (`NODE_ENV` is conventionally used to define the environment type, see [here](https://dzone.com/articles/what-you-should-know-about-node-env).) - -```bash -webpack --env.NODE_ENV=local --env.production --progress -``` - -T> Setting up your `env` variable without assignment, `--env.production` sets `--env.production` to `true` by default. There are also other syntaxes that you can use. See the [webpack CLI](/api/cli/#environment-options) documentation for more information. - -There is one change that you will have to make to your webpack config. Typically, `module.exports` points to the configuration object. To use the `env` variable, you must convert `module.exports` to a function: - -__webpack.config.js__ - -``` js -const path = require('path'); - -module.exports = env => { - // Use env.<YOUR VARIABLE> here: - console.log('NODE_ENV: ', env.NODE_ENV); // 'local' - console.log('Production: ', env.production); // true - - return { - entry: './src/index.js', - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist') - } - }; -}; -``` - - -# Build Performance - -This guide contains some useful tips for improving build/compilation performance. - ---- - -## General - -The following best practices should help, whether you're running build scripts in [development](/guides/development) or [production](/guides/production). - - -### Stay Up to Date - -Use the latest webpack version. We are always making performance improvements. The latest stable version of webpack is: - -[](https://github.com/webpack/webpack/releases) - -Staying up-to-date with __Node.js__ can also help with performance. On top of this, keeping your package manager (e.g. `npm` or `yarn`) up-to-date can also help. Newer versions create more efficient module trees and increase resolving speed. - - -### Loaders - -Apply loaders to the minimal number of modules necessary. Instead of: - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - loader: 'babel-loader' - } - ] - } -}; -``` - -Use the `include` field to only apply the loader modules that actually need to be transformed by it: - -```js -module.exports = { - //... - module: { - rules: [ - { - test: /\.js$/, - include: path.resolve(__dirname, 'src'), - loader: 'babel-loader' - } - ] - } -}; -``` - - -### Bootstrap - -Each additional loader/plugin has a bootup time. Try to use as few tools as possible. - - -### Resolving - -The following steps can increase resolving speed: - -- Minimize the number of items in `resolve.modules`, `resolve.extensions`, `resolve.mainFiles`, `resolve.descriptionFiles`, as they increase the number of filesystem calls. -- Set `resolve.symlinks: false` if you don't use symlinks (e.g. `npm link` or `yarn link`). -- Set `resolve.cacheWithContext: false` if you use custom resolving plugins, that are not context specific. - - -### Dlls - -Use the `DllPlugin` to move code that is changed less often into a separate compilation. This will improve the application's compilation speed, although it does increase complexity of the build process. - - -### Smaller = Faster - -Decrease the total size of the compilation to increase build performance. Try to keep chunks small. - -- Use fewer/smaller libraries. -- Use the `CommonsChunkPlugin` in Multi-Page Applications. -- Use the `CommonsChunkPlugin` in `async` mode in Multi-Page Applications. -- Remove unused code. -- Only compile the part of the code you are currently developing on. - - -### Worker Pool - -The `thread-loader` can be used to offload expensive loaders to a worker pool. - -W> Don't use too many workers, as there is a boot overhead for the Node.js runtime and the loader. Minimize the module transfers between worker and main process. IPC is expensive. - - -### Persistent cache - -Enable persistent caching with the `cache-loader`. Clear cache directory on `"postinstall"` in `package.json`. - - -### Custom plugins/loaders - -Profile them to not introduce a performance problem here. - ---- - - -## Development - -The following steps are especially useful in _development_. - - -### Incremental Builds - -Use webpack's watch mode. Don't use other tools to watch your files and invoke webpack. The built-in watch mode will keep track of timestamps and passes this information to the compilation for cache invalidation. - -In some setups, watching falls back to polling mode. With many watched files, this can cause a lot of CPU load. In these cases, you can increase the polling interval with `watchOptions.poll`. - - -### Compile in Memory - -The following utilities improve performance by compiling and serving assets in memory rather than writing to disk: - -- `webpack-dev-server` -- `webpack-hot-middleware` -- `webpack-dev-middleware` - -### stats.toJson speed - -webpack 4 outputs a large amount of data with its `stats.toJson()` by default. Avoid retrieving portions of the `stats` object unless necessary in the incremental step. `webpack-dev-server` after v3.1.3 contained a substantial performance fix to minimize the amount of data retrieved from the `stats` object per incremental build step. - -### Devtool - -Be aware of the performance differences of the different `devtool` settings. - -- `"eval"` has the best performance, but doesn't assist you for transpiled code. -- The `cheap-source-map` variants are more performant, if you can live with the slightly worse mapping quality. -- Use a `eval-source-map` variant for incremental builds. - -=> In most cases, `cheap-module-eval-source-map` is the best option. - - -### Avoid Production Specific Tooling - -Certain utilities, plugins, and loaders only make sense when building for production. For example, it usually doesn't make sense to minify and mangle your code with the `TerserPlugin` while in development. These tools should typically be excluded in development: - -- `TerserPlugin` -- `ExtractTextPlugin` -- `[hash]`/`[chunkhash]` -- `AggressiveSplittingPlugin` -- `AggressiveMergingPlugin` -- `ModuleConcatenationPlugin` - - -### Minimal Entry Chunk - -webpack only emits updated chunks to the filesystem. For some configuration options, (HMR, `[name]`/`[chunkhash]` in `output.chunkFilename`, `[hash]`) the entry chunk is invalidated in addition to the changed chunks. - -Make sure the entry chunk is cheap to emit by keeping it small. The following code block extracts a chunk containing only the runtime with _all other chunks as children_: - -```js -new CommonsChunkPlugin({ - name: 'manifest', - minChunks: Infinity -}); -``` - -### Avoid Extra Optimization Steps - -webpack does extra algorithmic work to optimize the output for size and load performance. These optimizations are performant for smaller codebases, but can be costly in larger ones: - -```js -module.exports = { - // ... - optimization: { - removeAvailableModules: false, - removeEmptyChunks: false, - splitChunks: false, - } -}; -``` - -### Output Without Path Info - -webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Turn this off in the `options.output.pathinfo` setting: - -```js -module.exports = { - // ... - output: { - pathinfo: false - } -}; -``` - -### Node.js Version - -There has been a [performance regression](https://github.com/nodejs/node/issues/19769) in the latest stable versions of Node.js and its ES2015 `Map` and `Set` implementations. A fix has been merged into master, but a release has yet to be made. In the meantime, to get the most out of incremental build speeds, try to stick with version 8.9.x (the problem exists between 8.9.10 - 9.11.1). webpack has moved to using those ES2015 data structures liberally, and it will improve the initial build times as well. - -### TypeScript Loader - -Recently, `ts-loader` has started to consume the internal TypeScript watch mode APIs which dramatically decreases the number of modules to be rebuilt on each iteration. This `experimentalWatchApi` shares the same logic as the normal TypeScript watch mode itself and is quite stable for development use. Turn on `transpileOnly`, as well, for even faster incremental builds. - -```js -module.exports = { - // ... - test: /\.tsx?$/, - use: [ - { - loader: 'ts-loader', - options: { - transpileOnly: true, - experimentalWatchApi: true, - }, - }, - ], -}; -``` - -Note: the `ts-loader` documentation suggests the use of `cache-loader`, but this actually slows the incremental builds down with disk writes. - -To gain typechecking again, use the [`ForkTsCheckerWebpackPlugin`](https://www.npmjs.com/package/fork-ts-checker-webpack-plugin). - -There is a [full example](https://github.com/TypeStrong/ts-loader/tree/master/examples/fast-incremental-builds) on the ts-loader github repository. - ---- - - -## Production - -The following steps are especially useful in _production_. - -W> __Don't sacrifice the quality of your application for small performance gains!__ Keep in mind that optimization quality is, in most cases, more important than build performance. - - -### Multiple Compilations - -When using multiple compilations, the following tools can help: - -- [`parallel-webpack`](https://github.com/trivago/parallel-webpack): It allows for compilation in a worker pool. -- `cache-loader`: The cache can be shared between multiple compilations. - - -### Source Maps - -Source maps are really expensive. Do you really need them? - ---- - - -## Specific Tooling Issues - -The following tools have certain problems that can degrade build performance: - - -### Babel - -- Minimize the number of preset/plugins - - -### TypeScript - -- Use the `fork-ts-checker-webpack-plugin` for typechecking in a separate process. -- Configure loaders to skip typechecking. -- Use the `ts-loader` in `happyPackMode: true` / `transpileOnly: true`. - - -### Sass - -- `node-sass` has a bug which blocks threads from the Node.js thread pool. When using it with the `thread-loader` set `workerParallelJobs: 2`. - - -# Content Security Policies - -Webpack is capable of adding `nonce` to all scripts that it loads. To activate the feature set a `__webpack_nonce__` variable needs to be included in your entry script. A unique hash based nonce should be generated and provided for each unique page view this is why `__webpack_nonce__` is specified in the entry file and not in the configuration. Please note that `nonce` should always be a base64-encoded string. - - -## Examples - -In the entry file: - -``` js -// ... -__webpack_nonce__ = 'c29tZSBjb29sIHN0cmluZyB3aWxsIHBvcCB1cCAxMjM='; -// ... -``` - - -## Enabling CSP - -Please note that CSPs are not enabled by default. A corresponding header `Content-Security-Policy` or meta tag `<meta http-equiv="Content-Security-Policy" ...>` needs to be sent with the document to instruct the browser to enable the CSP. Here's an example of what a CSP header including a CDN white-listed URL might look like: - -``` http -Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; -``` - -For more information on CSP and `nonce` attribute, please refer to __Further Reading__ section at the bottom of this page. - - -# Development - Vagrant - -If you have a more advanced project and use [Vagrant](https://www.vagrantup.com/) to run your development environment in a Virtual Machine, you'll often want to also run webpack in the VM. - -## Configuring the Project - -To start, make sure that the `Vagrantfile` has a static IP; - -```ruby -Vagrant.configure("2") do |config| - config.vm.network :private_network, ip: "10.10.10.61" -end -``` - -Next, install webpack and webpack-dev-server in your project; - -```bash -npm install --save-dev webpack webpack-dev-server -``` - -Make sure to have a `webpack.config.js` file. If you haven't already, use this as a minimal example to get started: - -```js -module.exports = { - context: __dirname, - entry: './app.js' -}; -``` - -And create a `index.html` file. The script tag should point to your bundle. If `output.filename` is not specified in the config, this will be `bundle.js`. - -```html -<!doctype html> -<html> - <head> - <script src="/bundle.js" charset="utf-8"></script> - </head> - <body> - <h2>Heey!</h2> - </body> -</html> -``` - -Note that you also need to create an `app.js` file. - -## Running the Server - -Now, let's run the server: - -```bash -webpack-dev-server --host 0.0.0.0 --public 10.10.10.61:8080 --watch-poll -``` - -By default the server will only be accessible from localhost. We'll be accessing it from our host PC, so we need to change `--host` to allow this. - -webpack-dev-server will include a script in your bundle that connects to a WebSocket to reload when a change in any of your files occurs. -The `--public` flag makes sure the script knows where to look for the WebSocket. The server will use port `8080` by default, so we should also specify that here. - -`--watch-poll` makes sure that webpack can detect changes in your files. By default webpack listens to events triggered by the filesystem, but VirtualBox has many problems with this. - -The server should be accessible on `http://10.10.10.61:8080` now. If you make a change in `app.js`, it should live reload. - -## Advanced Usage with nginx - -To mimic a more production-like environment, it is also possible to proxy the webpack-dev-server with nginx. - -In your nginx config file, add the following: - -```nginx -server { - location / { - proxy_pass http://127.0.0.1:8080; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - error_page 502 @start-webpack-dev-server; - } - - location @start-webpack-dev-server { - default_type text/plain; - return 502 "Please start the webpack-dev-server first."; - } -} -``` - -The `proxy_set_header` lines are important, because they allow the WebSockets to work correctly. - -The command to start webpack-dev-server can then be changed to this: - -```bash -webpack-dev-server --public 10.10.10.61 --watch-poll -``` - -This makes the server only accessible on `127.0.0.1`, which is fine, because nginx takes care of making it available on your host PC. - -## Conclusion - -We made the Vagrant box accessible from a static IP, and then made webpack-dev-server publicly accessible so it is reachable from a browser. We then tackled a common problem that VirtualBox doesn't send out filesystem events, causing the server to not reload on file changes. - - -# Dependency Management - -> es6 modules - -> commonjs - -> amd - - -## require with expression - -A context is created if your request contains expressions, so the __exact__ module is not known on compile time. - -Example: - -```javascript -require('./template/' + name + '.ejs'); -``` - -webpack parses the `require()` call and extracts some information: - -```code -Directory: ./template -Regular expression: /^.*\.ejs$/ -``` - -__context module__ - -A context module is generated. It contains references to __all modules in that directory__ that can be required with a request matching the regular expression. The context module contains a map which translates requests to module ids. - -Example: - -```json -{ - "./table.ejs": 42, - "./table-row.ejs": 43, - "./directory/folder.ejs": 44 -} -``` - -The context module also contains some runtime logic to access the map. - -This means dynamic requires are supported but will cause all possible modules to be included in the bundle. - - -## `require.context` - -You can create your own context with the `require.context()` function. - -It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched -too, and a regular expression to match files against. - -webpack parses for `require.context()` in the code while building. - -The syntax is as follows: - -```javascript -require.context(directory, useSubdirectories = false, regExp = /^\.\//); -``` - -Examples: - -```javascript -require.context('./test', false, /\.test\.js$/); -// a context with files from the test directory that can be required with a request endings with `.test.js`. -``` - -```javascript -require.context('../', true, /\.stories\.js$/); -// a context with all files in the parent folder and descending folders ending with `.stories.js`. -``` - -W> The arguments passed to `require.context` must be literals! - - -### context module API - -A context module exports a (require) function that takes one argument: the request. - -The exported function has 3 properties: `resolve`, `keys`, `id`. - -- `resolve` is a function and returns the module id of the parsed request. -- `keys` is a function that returns an array of all possible requests that the context module can handle. - -This can be useful if you want to require all files in a directory or matching a pattern, Example: - -```javascript -function importAll (r) { - r.keys().forEach(r); -} - -importAll(require.context('../components/', true, /\.js$/)); -``` - -```javascript -var cache = {}; - -function importAll (r) { - r.keys().forEach(key => cache[key] = r(key)); -} - -importAll(require.context('../components/', true, /\.js$/)); -// At build-time cache will be populated with all required modules. -``` - -- `id` is the module id of the context module. This may be useful for `module.hot.accept`. - - -# Public Path - -The `publicPath` configuration option can be quite useful in a variety of scenarios. It allows you to specify the base path for all the assets within your application. - - -## Use Cases - -There are a few use cases in real applications where this feature becomes especially neat. Essentially, every file emitted to your `output.path` directory will be referenced from the `output.publicPath` location. This includes child chunks (created via [code splitting](/guides/code-splitting/)) and any other assets (e.g. images, fonts, etc.) that are a part of your dependency graph. - -### Environment Based - -In development for example, we might have an `assets/` folder that lives on the same level of our index page. This is fine, but what if we wanted to host all these static assets on a CDN in production? - -To approach this problem you can easily use a good old environment variable. Let's say we have a variable `ASSET_PATH`: - -``` js -import webpack from 'webpack'; - -// Try the environment variable, otherwise use root -const ASSET_PATH = process.env.ASSET_PATH || '/'; - -export default { - output: { - publicPath: ASSET_PATH - }, - - plugins: [ - // This makes it possible for us to safely use env vars on our code - new webpack.DefinePlugin({ - 'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH) - }) - ] -}; -``` - -### On The Fly - -Another possible use case is to set the `publicPath` on the fly. webpack exposes a global variable called `__webpack_public_path__` that allows you to do that. So, in your application's entry point, you can simply do this: - -```js -__webpack_public_path__ = process.env.ASSET_PATH; -``` - -That's all you need. Since we're already using the `DefinePlugin` on our -configuration, `process.env.ASSET_PATH` will always be defined so we can safely -do that. - -W> Be aware that if you use ES6 module imports in your entry file the `__webpack_public_path__` assignment will be done after the imports. In such cases, you'll have to move the public path assignment to its own dedicated module and then import it on top of your entry.js: - -```js -// entry.js -import './public-path'; -import './app'; -``` - - -# Integrations - -Let's start by clearing up a common misconception. webpack is a module bundler like [Browserify](http://browserify.org/) or [Brunch](http://brunch.io/). It is _not a task runner_ like [Make](https://www.gnu.org/software/make/), [Grunt](https://gruntjs.com/), or [Gulp](https://gulpjs.com/). Task runners handle automation of common development tasks such as linting, building, or testing your project. Compared to bundlers, task runners have a higher level focus. You can still benefit from their higher level tooling while leaving the problem of bundling to webpack. - -Bundlers help you get your JavaScript and stylesheets ready for deployment, transforming them into a format that's suitable for the browser. For example, JavaScript can be [minified](/plugins/terser-webpack-plugin) or [split into chunks](/guides/code-splitting) and [lazy-loaded](/guides/lazy-loading) to improve performance. Bundling is one of the most important challenges in web development, and solving it well can remove a lot of pain from the process. - -The good news is that, while there is some overlap, task runners and bundlers can play well together if approached in the right way. This guide provides a high-level overview of how webpack can be integrated into some of the more popular task runners. - - -## NPM Scripts - -Often webpack users use npm [`scripts`](https://docs.npmjs.com/misc/scripts) as their task runner. This is a good starting point. Cross-platform support can become a problem, but there are several workarounds for that. Many, if not most users, get by with simple npm `scripts` and various levels of webpack configuration and tooling. - -So while webpack's core focus is bundling, there are a variety of extensions that can enable you to use it for jobs typical of a task runner. Integrating a separate tool adds complexity, so be sure to weigh the pros and cons before going forward. - - -## Grunt - -For those using Grunt, we recommend the [`grunt-webpack`](https://www.npmjs.com/package/grunt-webpack) package. With `grunt-webpack` you can run webpack or [webpack-dev-server](https://github.com/webpack/webpack-dev-server) as a task, get access to stats within [template tags](https://gruntjs.com/api/grunt.template), split development and production configurations and more. Start by installing `grunt-webpack` as well as `webpack` itself if you haven't already: - -``` bash -npm install --save-dev grunt-webpack webpack -``` - -Then register a configuration and load the task: - -__Gruntfile.js__ - -``` js -const webpackConfig = require('./webpack.config.js'); - -module.exports = function(grunt) { - grunt.initConfig({ - webpack: { - options: { - stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development' - }, - prod: webpackConfig, - dev: Object.assign({ watch: true }, webpackConfig) - } - }); - - grunt.loadNpmTasks('grunt-webpack'); -}; -``` - -For more information, please visit the [repository](https://github.com/webpack-contrib/grunt-webpack). - - -## Gulp - -Gulp is also a fairly straightforward integration with the help of the [`webpack-stream`](https://github.com/shama/webpack-stream) package (a.k.a. `gulp-webpack`). In this case, it is unnecessary to install `webpack` separately as it is a direct dependency of `webpack-stream`: - -``` bash -npm install --save-dev webpack-stream -``` - -Just `require('webpack-stream')` instead of `webpack` and optionally pass it an configuration: - -__gulpfile.js__ - -``` js -var gulp = require('gulp'); -var webpack = require('webpack-stream'); -gulp.task('default', function() { - return gulp.src('src/entry.js') - .pipe(webpack({ - // Any configuration options... - })) - .pipe(gulp.dest('dist/')); -}); -``` - -For more information, please visit the [repository](https://github.com/shama/webpack-stream). - - -## Mocha - -The [`mocha-webpack`](https://github.com/zinserjan/mocha-webpack) utility can be used for a clean integration with Mocha. The repository offers more details on the pros and cons but essentially `mocha-webpack` is a simple wrapper that provides almost the same CLI as Mocha itself and provides various webpack functionality like an improved watch mode and improved path resolution. Here is a small example of how you would install it and use it to run a test suite (found within `./test`): - -``` bash -npm install --save-dev webpack mocha mocha-webpack -mocha-webpack 'test/**/*.js' -``` - -For more information, please visit the [repository](https://github.com/zinserjan/mocha-webpack). - - -## Karma - -The [`karma-webpack`](https://github.com/webpack-contrib/karma-webpack) package allows you to use webpack to pre-process files in [Karma](http://karma-runner.github.io/1.0/index.html). It also makes use of [`webpack-dev-middleware`](https://github.com/webpack/webpack-dev-middleware) and allows passing configurations for both. A simple example may look something like this: - -``` bash -npm install --save-dev webpack karma karma-webpack -``` - -__karma.conf.js__ - -``` js -module.exports = function(config) { - config.set({ - files: [ - { pattern: 'test/*_test.js', watched: false }, - { pattern: 'test/**/*_test.js', watched: false } - ], - preprocessors: { - 'test/*_test.js': [ 'webpack' ], - 'test/**/*_test.js': [ 'webpack' ] - }, - webpack: { - // Any custom webpack configuration... - }, - webpackMiddleware: { - // Any custom webpack-dev-middleware configuration... - } - }); -}; -``` - -For more information, please visit the [repository](https://github.com/webpack-contrib/karma-webpack). diff --git a/src/content/loaders/_loaders_all.md b/src/content/loaders/_loaders_all.md deleted file mode 100644 index a16e6814c65b..000000000000 --- a/src/content/loaders/_loaders_all.md +++ /dev/null @@ -1,75 +0,0 @@ - - -# Loaders - -webpack enables use of [loaders](/concepts/loaders) to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js. - -Loaders are activated by using `loadername!` prefixes in `require()` statements, or are automatically applied via regex from your webpack configuration – see [configuration](/concepts/loaders#configuration). - - -## Files - -- [`raw-loader`](/loaders/raw-loader) Loads raw content of a file (utf-8) -- [`val-loader`](/loaders/val-loader) Executes code as module and consider exports as JS code -- [`url-loader`](/loaders/url-loader) Works like the file loader, but can return a [data URL](https://tools.ietf.org/html/rfc2397) if the file is smaller than a limit -- [`file-loader`](/loaders/file-loader) Emits the file into the output folder and returns the (relative) URL -- [`ref-loader`](https://www.npmjs.com/package/ref-loader) Create dependencies between any files manually - - -## JSON - -- [`json-loader`](/loaders/json-loader) Loads a [JSON](http://json.org/) file (included by default) -- [`json5-loader`](/loaders/json5-loader) Loads and transpiles a [JSON 5](https://json5.org/) file -- [`cson-loader`](https://github.com/awnist/cson-loader) Loads and transpiles a [CSON](https://github.com/bevry/cson#what-is-cson) file - - -## Transpiling - -- [`script-loader`](/loaders/script-loader) Executes a JavaScript file once in global context (like in script tag), requires are not parsed -- [`babel-loader`](/loaders/babel-loader) Loads ES2015+ code and transpiles to ES5 using [Babel](https://babeljs.io/) -- [`buble-loader`](https://github.com/sairion/buble-loader) Loads ES2015+ code and transpiles to ES5 using [Bublé](https://buble.surge.sh/guide/) -- [`traceur-loader`](https://github.com/jupl/traceur-loader) Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler#readme) -- [`ts-loader`](https://github.com/TypeStrong/ts-loader) or [`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader) Loads [TypeScript](https://www.typescriptlang.org/) 2.0+ like JavaScript -- [`coffee-loader`](/loaders/coffee-loader) Loads [CoffeeScript](http://coffeescript.org/) like JavaScript -- [`fengari-loader`](https://github.com/fengari-lua/fengari-loader/) Loads Lua code using [fengari](https://fengari.io/) - - -## Templating - -- [`html-loader`](/loaders/html-loader) Exports HTML as string, require references to static resources -- [`pug-loader`](https://github.com/pugjs/pug-loader) Loads Pug and Jade templates and returns a function -- [`markdown-loader`](https://github.com/peerigon/markdown-loader) Compiles Markdown to HTML -- [`react-markdown-loader`](https://github.com/javiercf/react-markdown-loader) Compiles Markdown to a React Component using the markdown-parse parser -- [`posthtml-loader`](https://github.com/posthtml/posthtml-loader) Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) -- [`handlebars-loader`](https://github.com/pcardune/handlebars-loader) Compiles Handlebars to HTML -- [`markup-inline-loader`](https://github.com/asnowwolf/markup-inline-loader) Inline SVG/MathML files to HTML. It’s useful when applying icon font or applying CSS animation to SVG. -- [`twig-loader`](https://github.com/zimmo-be/twig-loader) Compiles Twig templates and returns a function - -## Styling - -- [`style-loader`](/loaders/style-loader) Add exports of a module as style to DOM -- [`css-loader`](/loaders/css-loader) Loads CSS file with resolved imports and returns CSS code -- [`less-loader`](/loaders/less-loader) Loads and compiles a LESS file -- [`sass-loader`](/loaders/sass-loader) Loads and compiles a SASS/SCSS file -- [`postcss-loader`](/loaders/postcss-loader) Loads and transforms a CSS/SSS file using [PostCSS](http://postcss.org) -- [`stylus-loader`](https://github.com/shama/stylus-loader) Loads and compiles a Stylus file - - -## Linting && Testing - -- [`mocha-loader`](/loaders/mocha-loader) Tests with [mocha](https://mochajs.org/) (Browser/NodeJS) -- [`eslint-loader`](https://github.com/webpack-contrib/eslint-loader) PreLoader for linting code using [ESLint](https://eslint.org/) -- [`jshint-loader`](/loaders/jshint-loader) PreLoader for linting code using [JSHint](http://jshint.com/about/) -- [`jscs-loader`](https://github.com/unindented/jscs-loader) PreLoader for code style checking using [JSCS](http://jscs.info/) -- [`coverjs-loader`](/loaders/coverjs-loader) PreLoader to determine the testing coverage using [CoverJS](https://github.com/arian/CoverJS) - - -## Frameworks - -- [`vue-loader`](https://github.com/vuejs/vue-loader) Loads and compiles [Vue Components](https://vuejs.org/v2/guide/components.html) -- [`polymer-loader`](https://github.com/webpack-contrib/polymer-webpack-loader) Process HTML & CSS with preprocessor of choice and `require()` Web Components like first-class modules -- [`angular2-template-loader`](https://github.com/TheLarkInn/angular2-template-loader) Loads and compiles [Angular](https://angular.io/) Components - - - -For more third-party loaders, see the list from [awesome-webpack](https://github.com/webpack-contrib/awesome-webpack#loaders). diff --git a/src/content/migrate/_migrate_all.md b/src/content/migrate/_migrate_all.md deleted file mode 100644 index c0c02cb9ff2b..000000000000 --- a/src/content/migrate/_migrate_all.md +++ /dev/null @@ -1,786 +0,0 @@ - - -# Migrate - -This section contains information about migrating from older versions of webpack to newer ones. - -# To v4 from v3 - -This guide only shows major changes that affect end users. For more details please see [the changelog](https://github.com/webpack/webpack/releases). - - -## Node.js v4 - -If you are still using Node.js v4 or lower, you need to upgrade your Node.js installation to Node.js v6 or higher. - - -## CLI - -The CLI has moved to a separate package: webpack-cli. You need to install it before using webpack, see [basic setup](/guides/getting-started/#basic-setup). - - -## Update plugins - -Many 3rd-party plugins need to be upgraded to their latest version to be compatible. - - -## mode - -Add the new [`mode`](/concepts/mode/) option to your config. Set it to production or development in your configuration depending on config type. - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - mode: 'production', -} -``` - -Alternatively you can pass it via CLI: `--mode production`/`--mode development` - -## Deprecated/Removed plugins - -These plugins can be removed from configuration as they are default in production mode: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NoEmitOnErrorsPlugin(), -- new ModuleConcatenationPlugin(), -- new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }) -- new UglifyJsPlugin() - ], -} -``` - -These plugins are default in development mode - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NamedModulesPlugin() - ], -} -``` - -These plugins were deprecated and are now removed: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - plugins: [ -- new NoErrorsPlugin(), -- new NewWatchingPlugin() - ], -} -``` - - -## CommonsChunkPlugin - -The `CommonsChunkPlugin` was removed. Instead the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) options can be used. - -See documentation of the [`optimization.splitChunks`](/configuration/optimization/#optimization-splitchunks) for more details. The default configuration may already suit your needs. - -T> When generating the HTML from the stats you can use `optimization.splitChunks.chunks: "all"` which is the optimal configuration in most cases. - -## import() and CommonJS - -When using `import()` to load non-ESM the result has changed in webpack 4. Now you need to access the `default` property to get the value of `module.exports`. - -__non-esm.js__ - -``` javascript -module.exports = { - sayHello: () => { - console.log('hello world'); - } -}; -``` - -__example.js__ - -``` javascript -function sayHello() { - import('./non-esm.js').then(module => { - module.default.sayHello(); - }); -} -``` - -## json and loaders - -When using a custom loader to transform `.json` files you now need to change the module `type`: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - rules: [ - { - test: /config\.json$/, - loader: 'special-loader', -+ type: 'javascript/auto', - options: {...} - } - ] -}; -``` - -When still using the `json-loader`, it can be removed: - -__webpack.config.js__ - -``` diff -module.exports = { - // ... - rules: [ - { -- test: /\.json$/, -- loader: 'json-loader' - } - ] -}; -``` - -## module.loaders - -`module.loaders` were deprecated since webpack 2 and are now removed in favor of [`module.rules`](/configuration/module/#rule). - - -# To v2 or v3 from v1 - -The following sections describe the major changes from webpack 1 to 2. - -T> Note that there were far fewer changes between 2 and 3, so that migration shouldn't be too bad. If you are running into issues, please see [the changelog](https://github.com/webpack/webpack/releases) for details. - - -## `resolve.root`, `resolve.fallback`, `resolve.modulesDirectories` - -These options were replaced by a single option `resolve.modules`. See [resolving](/configuration/resolve) for more usage. - -``` diff - resolve: { -- root: path.join(__dirname, "src") -+ modules: [ -+ path.join(__dirname, "src"), -+ "node_modules" -+ ] - } -``` - - -## `resolve.extensions` - -This option no longer requires passing an empty string. This behavior was moved to `resolve.enforceExtension`. See [resolving](/configuration/resolve) for more usage. - - -## `resolve.*` - -Several APIs were changed here. Not listed in detail as it's not commonly used. See [resolving](/configuration/resolve) for details. - - -## `module.loaders` is now `module.rules` - -The old loader configuration was superseded by a more powerful rules system, which allows configuration of loaders and more. -For compatibility reasons, the old `module.loaders` syntax is still valid and the old names are parsed. -The new naming conventions are easier to understand and are a good reason to upgrade the configuration to using `module.rules`. - -``` diff - module: { -- loaders: [ -+ rules: [ - { - test: /\.css$/, -- loaders: [ -- "style-loader", -- "css-loader?modules=true" -+ use: [ -+ { -+ loader: "style-loader" -+ }, -+ { -+ loader: "css-loader", -+ options: { -+ modules: true -+ } -+ } - ] - }, - { - test: /\.jsx$/, - loader: "babel-loader", // Do not use "use" here - options: { - // ... - } - } - ] - } -``` - - -## Chaining loaders - -Like in webpack 1, loaders can be chained to pass results from loader to loader. Using the [rule.use](/configuration/module#rule-use) - configuration option, `use` can be set to an array of loaders. -In webpack 1, loaders were commonly chained with `!`. This style is only supported using the legacy option `module.loaders`. - -``` diff - module: { -- loaders: [{ -+ rules: [{ - test: /\.less$/, -- loader: "style-loader!css-loader!less-loader" -+ use: [ -+ "style-loader", -+ "css-loader", -+ "less-loader" -+ ] - }] - } -``` - - -## Automatic `-loader` module name extension removed - -It is not possible anymore to omit the `-loader` extension when referencing loaders: - -``` diff - module: { - rules: [ - { - use: [ -- "style", -+ "style-loader", -- "css", -+ "css-loader", -- "less", -+ "less-loader", - ] - } - ] - } -``` - -You can still opt-in to the old behavior with the `resolveLoader.moduleExtensions` configuration option, but this is not recommended. - -``` diff -+ resolveLoader: { -+ moduleExtensions: ["-loader"] -+ } -``` - -See [#2986](https://github.com/webpack/webpack/issues/2986) for the reason behind this change. - - -## `json-loader` is not required anymore - -When no loader has been configured for a JSON file, webpack will automatically try to load the JSON -file with the [`json-loader`](https://github.com/webpack-contrib/json-loader). - -``` diff - module: { - rules: [ -- { -- test: /\.json/, -- loader: "json-loader" -- } - ] - } -``` - -[We decided to do this](https://github.com/webpack/webpack/issues/3363) in order to iron out environment differences - between webpack, node.js and browserify. - - -## Loaders in configuration resolve relative to context - -In __webpack 1__, configured loaders resolve relative to the matched file. However, in __webpack 2__, configured loaders resolve relative to the `context` option. - -This solves some problems with duplicate modules caused by loaders when using `npm link` or referencing modules outside of the `context`. - -You may remove some hacks to work around this: - -``` diff - module: { - rules: [ - { - // ... -- loader: require.resolve("my-loader") -+ loader: "my-loader" - } - ] - }, - resolveLoader: { -- root: path.resolve(__dirname, "node_modules") - } -``` - - -## `module.preLoaders` and `module.postLoaders` were removed: - -``` diff - module: { -- preLoaders: [ -+ rules: [ - { - test: /\.js$/, -+ enforce: "pre", - loader: "eslint-loader" - } - ] - } -``` - - -## `UglifyJsPlugin` sourceMap - -The `sourceMap` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. This means that if you are using source maps for minimized code or want correct line numbers for uglifyjs warnings, you need to set `sourceMap: true` for `UglifyJsPlugin`. - -``` diff - devtool: "source-map", - plugins: [ - new UglifyJsPlugin({ -+ sourceMap: true - }) - ] -``` - - -## `UglifyJsPlugin` warnings - -The `compress.warnings` option of the `UglifyJsPlugin` now defaults to `false` instead of `true`. -This means that if you want to see uglifyjs warnings, you need to set `compress.warnings` to `true`. - -``` diff - devtool: "source-map", - plugins: [ - new UglifyJsPlugin({ -+ compress: { -+ warnings: true -+ } - }) - ] -``` - - -## `UglifyJsPlugin` minimize loaders - -`UglifyJsPlugin` no longer switches loaders into minimize mode. The `minimize: true` setting needs to be passed via loader options in the long-term. See loader documentation for relevant options. - -The minimize mode for loaders will be removed in webpack 3 or later. - -To keep compatibility with old loaders, loaders can be switched to minimize mode via plugin: - -``` diff - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ minimize: true -+ }) - ] -``` - - -## `DedupePlugin` has been removed - -`webpack.optimize.DedupePlugin` isn't needed anymore. Remove it from your configuration. - - -## `BannerPlugin` - breaking change - -`BannerPlugin` no longer accepts two parameters, but a single options object. - -``` diff - plugins: [ -- new webpack.BannerPlugin('Banner', {raw: true, entryOnly: true}); -+ new webpack.BannerPlugin({banner: 'Banner', raw: true, entryOnly: true}); - ] -``` - - -## `OccurrenceOrderPlugin` is now on by default - -The `OccurrenceOrderPlugin` is now enabled by default and has been renamed (`OccurenceOrderPlugin` in webpack 1). -Thus make sure to remove the plugin from your configuration: - -``` diff - plugins: [ - // webpack 1 -- new webpack.optimize.OccurenceOrderPlugin() - // webpack 2 -- new webpack.optimize.OccurrenceOrderPlugin() - ] -``` - - -## `ExtractTextWebpackPlugin` - breaking change - -[ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) requires version 2 to work with webpack 2. - -`npm install --save-dev extract-text-webpack-plugin` - -The configuration changes for this plugin are mainly syntactical. - -### `ExtractTextPlugin.extract` - -```diff -module: { - rules: [ - { - test: /.css$/, -- loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" }) -+ use: ExtractTextPlugin.extract({ -+ fallback: "style-loader", -+ use: "css-loader", -+ publicPath: "/dist" -+ }) - } - ] -} -``` - - -### `new ExtractTextPlugin({options})` - -```diff -plugins: [ -- new ExtractTextPlugin("bundle.css", { allChunks: true, disable: false }) -+ new ExtractTextPlugin({ -+ filename: "bundle.css", -+ disable: false, -+ allChunks: true -+ }) -] -``` - - -## Full dynamic requires now fail by default - -A dependency with only an expression (i. e. `require(expr)`) will now create an empty context instead of the context of the complete directory. - -Code like this should be refactored as it won't work with ES2015 modules. If this is not possible you can use the `ContextReplacementPlugin` to hint the compiler towards the correct resolving. - -?> Link to an article about dynamic dependencies. - -### Using custom arguments in CLI and configuration - -If you abused the CLI to pass custom arguments to the configuration like so: - -`webpack --custom-stuff` - -```js -// webpack.config.js -var customStuff = process.argv.indexOf('--custom-stuff') >= 0; -/* ... */ -module.exports = config; -``` - -You may notice that this is no longer allowed. The CLI is more strict now. - -Instead there is an interface for passing arguments to the configuration. This should be used instead. Future tools may rely on this. - -`webpack --env.customStuff` - -```js -module.exports = function(env) { - var customStuff = env.customStuff; - /* ... */ - return config; -}; -``` - -See [CLI](/api/cli). - - -## `require.ensure` and AMD `require` are asynchronous - -These functions are now always asynchronous instead of calling their callback synchronously if the chunk is already loaded. - -__`require.ensure` now depends upon native `Promise`s. If using `require.ensure` in an environment that lacks them then you will need a polyfill.__ - - -## Loader configuration is through `options` - -You can _no longer_ configure a loader with a custom property in the `webpack.config.js`. It must be done through the `options`. The following configuration with the `ts` property is no longer valid with webpack 2: - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader' - }] - }, - // does not work with webpack 2 - ts: { transpileOnly: false } -}; -``` - - -### What are `options`? - -Good question. Well, strictly speaking it's 2 possible things; both ways to configure a webpack loader. Classically `options` was called `query` and was a string which could be appended to the name of the loader. Much like a query string but actually with [greater powers](https://github.com/webpack/loader-utils#parsequery): - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader?' + JSON.stringify({ transpileOnly: false }) - }] - } -}; -``` - -But it can also be a separately specified object that's supplied alongside a loader: - -```js -module.exports = { - //... - module: { - rules: [{ - test: /\.tsx?$/, - loader: 'ts-loader', - options: { transpileOnly: false } - }] - } -}; -``` - - -## `LoaderOptionsPlugin` context - -Some loaders need context information and read them from the configuration. This needs to be passed via loader options in the long-term. See loader documentation for relevant options. - -To keep compatibility with old loaders, this information can be passed via plugin: - -``` diff - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ options: { -+ context: __dirname -+ } -+ }) - ] -``` - - -## `debug` - -The `debug` option switched loaders to debug mode in webpack 1. This needs to be passed via loader options in long-term. See loader documentation for relevant options. - -The debug mode for loaders will be removed in webpack 3 or later. - -To keep compatibility with old loaders, loaders can be switched to debug mode via a plugin: - -``` diff -- debug: true, - plugins: [ -+ new webpack.LoaderOptionsPlugin({ -+ debug: true -+ }) - ] -``` - - -## Code Splitting with ES2015 - -In webpack 1, you could use [`require.ensure()`](/api/module-methods#require-ensure) as a method to lazily-load chunks for your application: - -```javascript -require.ensure([], function(require) { - var foo = require('./module'); -}); -``` - -The ES2015 Loader spec defines [`import()`](/api/module-methods#import-) as method to load ES2015 Modules dynamically on runtime. webpack treats `import()` as a split-point and puts the requested module in a separate chunk. `import()` takes the module name as argument and returns a Promise. - -```js -function onClick() { - import('./module').then(module => { - return module.default; - }).catch(err => { - console.log('Chunk loading failed'); - }); -} -``` - -Good news: Failure to load a chunk can now be handled because they are `Promise` based. - - -## Dynamic expressions - -It's possible to pass a partial expression to `import()`. This is handled similar to expressions in CommonJS (webpack creates a [context](/plugins/context-replacement-plugin/) with all possible files). - -`import()` creates a separate chunk for each possible module. - -```js -function route(path, query) { - return import(`./routes/${path}/route`) - .then(route => new route.Route(query)); -} -// This creates a separate chunk for each possible route -``` - - -## Mixing ES2015 with AMD and CommonJS - -As for AMD and CommonJS you can freely mix all three module types (even within the same file). webpack behaves similar to babel and node-eps in this case: - -```javascript -// CommonJS consuming ES2015 Module -var book = require('./book'); - -book.currentPage; -book.readPage(); -book.default === 'This is a book'; -``` - -```javascript -// ES2015 Module consuming CommonJS -import fs from 'fs'; // module.exports map to default -import { readFileSync } from 'fs'; // named exports are read from returned object+ - -typeof fs.readFileSync === 'function'; -typeof readFileSync === 'function'; -``` - -It is important to note that you will want to tell Babel to not parse these module symbols so webpack can use them. You can do this by setting the following in your `.babelrc` or `babel-loader` options. - -__.babelrc__ - -```json -{ - "presets": [ - ["es2015", { "modules": false }] - ] -} -``` - - -## Hints - -No need to change something, but opportunities - -### Template strings - -webpack now supports template strings in expressions. This means you can start using them in webpack constructs: - -``` diff -- require("./templates/" + name); -+ require(`./templates/${name}`); -``` - - -### Configuration Promise - -webpack now supports returning a `Promise` from the configuration file. This allows async processing in your configuration file. - -__webpack.config.js__ - -```js -module.exports = function() { - return fetchLangs().then(lang => ({ - entry: '...', - // ... - plugins: [ - new DefinePlugin({ LANGUAGE: lang }) - ] - })); -}; -``` - - -### Advanced loader matching - -webpack now supports more things to match on for loaders. - -```js -module.exports = { - //... - module: { - rules: [ - { - resource: /filename/, // matches "/path/filename.js" - resourceQuery: /^\?querystring$/, // matches "?querystring" - issuer: /filename/, // matches "/path/something.js" if requested from "/path/filename.js" - } - ] - } -}; -``` - - -### More CLI options - -There are some new CLI options for you to use: - -`--define process.env.NODE_ENV="production"` See [`DefinePlugin`](/plugins/define-plugin/). - -`--display-depth` displays the distance to the entry point for each module. - -`--display-used-exports` display info about which exports are used in a module. - -`--display-max-modules` sets the number for modules displayed in the output (defaults to 15). - -`-p` also defines `process.env.NODE_ENV` to `"production"` now. - - -## Loader changes - -Changes only relevant for loader authors. - - -### Cacheable - -Loaders are now cacheable by default. Loaders must opt-out if they are not cacheable. - -``` diff - // Cacheable loader - module.exports = function(source) { -- this.cacheable(); - return source; - } -``` - -``` diff - // Not cacheable loader - module.exports = function(source) { -+ this.cacheable(false); - return source; - } -``` - - -### Complex options - -__webpack 1__ only supports `JSON.stringify`-able options for loaders. - -__webpack 2__ now supports any JS object as loader options. - -Before webpack [2.2.1](https://github.com/webpack/webpack/releases/tag/v2.2.1) (i.e. from 2.0.0 through 2.2.0), using complex options required using `ident` for the `options` object to allow its reference from other loaders. __This was removed in 2.2.1__ and thus current migrations do not require any use of the `ident` key. - -```diff -{ - test: /\.ext/ - use: { - loader: '...', - options: { -- ident: 'id', - fn: () => require('./foo.js') - } - } -} -``` diff --git a/src/content/plugins/_plugins_all.md b/src/content/plugins/_plugins_all.md deleted file mode 100644 index 65d63475ab80..000000000000 --- a/src/content/plugins/_plugins_all.md +++ /dev/null @@ -1,11 +0,0 @@ - - -# MinChunkSizePlugin - -Keep chunk size above the specified limit by merging chunks that are smaller than the `minChunkSize`. - -``` js -new webpack.optimize.MinChunkSizePlugin({ - minChunkSize: 10000 // Minimum number of characters -}); -``` From 2a90c76d09887e07421be2a3eb69d1dc2bb43147 Mon Sep 17 00:00:00 2001 From: Axel D <SetTrend@users.noreply.github.com> Date: Wed, 23 Jan 2019 15:37:23 +0100 Subject: [PATCH 13/13] Configuration for summarized help files removed from `package.json`. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 931acebc9f52..0cc1e167f949 100644 --- a/package.json +++ b/package.json @@ -26,14 +26,14 @@ "scripts": { "start": "run-s -n init:generated fetch start-only", "start-only": "node ./antwar.bootstrap.js develop", - "build": "npm run init:generated && npm run fetch && rm -rf build/ && node ./antwar.bootstrap.js build && npm run sitemap && npm run chapterize && echo webpack.js.org > build/CNAME", + "build": "npm run init:generated && npm run fetch && rm -rf build/ && node ./antwar.bootstrap.js build && npm run sitemap && echo webpack.js.org > build/CNAME", "build-test": "npm run build && http-server build/", "deploy": "gh-pages -d build", "fetch": "sh src/scripts/fetch.sh", "init:generated": "mkdirp ./generated/loaders && mkdirp ./generated/plugins ", "lint": "run-s lint:*", "lint:js": "eslint . --ext .js,.jsx,.md", - "lint:markdown": "markdownlint --rules markdownlint-rule-emphasis-style --config ./.markdownlint.json --ignore ./src/content/**/*_all.md *.md ./src/content/**/*.md", + "lint:markdown": "markdownlint --rules markdownlint-rule-emphasis-style --config ./.markdownlint.json --ignore *.md ./src/content/**/*.md", "lint:social": "alex . -q", "lint:prose": "cp .proselintrc ~/ && proselint src/content", "test": "npm run lint",