From 3f5c3fb8b89c9d9919099893a4fb91b02b333c84 Mon Sep 17 00:00:00 2001 From: Greg Venech Date: Thu, 7 Sep 2017 23:38:40 -0400 Subject: [PATCH 01/22] docs(api): minor fix in cli Make minor fix in the CLI documentation to reflect this comment: https://github.com/webpack/webpack.js.org/issues/1577#issuecomment-327721426 --- src/content/api/cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/api/cli.md b/src/content/api/cli.md index 7d1e5d9edf65..3ec1843584f1 100644 --- a/src/content/api/cli.md +++ b/src/content/api/cli.md @@ -292,7 +292,7 @@ Parameter | Explanation | Usage Shortcut | Replaces ---------|---------------------------- --d | `--debug --devtool cheap-module-source-map --output-pathinfo` +-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) From 9cd50d5abd838f22f1a3b065aa524d791465d1cf Mon Sep 17 00:00:00 2001 From: Greg Venech Date: Fri, 8 Sep 2017 01:22:20 -0400 Subject: [PATCH 02/22] docs(plugins): clarify and simplify `SourceMapDevToolPlugin` docs (#1581) Try to resolve the confusion from #1556. Also update the options section to clean things up a bit both for readability and grammar. Resolves #1556 --- .../plugins/source-map-dev-tool-plugin.md | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/content/plugins/source-map-dev-tool-plugin.md b/src/content/plugins/source-map-dev-tool-plugin.md index f008558c8601..0b613b6cc598 100644 --- a/src/content/plugins/source-map-dev-tool-plugin.md +++ b/src/content/plugins/source-map-dev-tool-plugin.md @@ -8,7 +8,7 @@ related: url: https://survivejs.com/webpack/building/source-maps/#-sourcemapdevtoolplugin-and-evalsourcemapdevtoolplugin- --- -This plugin enables a more fine grained control of [source maps added via the `devtool` option](/configuration/devtool/). +This plugin enables more fine grained control of source map generation. It is an alternative to the [`devtool`](/configuration/devtool/) configuration option. ```javascript new webpack.SourceMapDevToolPlugin(options) @@ -19,13 +19,20 @@ new webpack.SourceMapDevToolPlugin(options) The following options are supported: -* `options.test` / `options.include` / `options.exclude` (`string|RegExp|Array`): Used to determine which assets should be processed. Each one can be a `RegExp` (asset filename is matched), a `string` (asset filename need to start with this string) or an `Array` of those (any of them need to be matched). `test` defaults to `.js` and `.css` files if omitted. -* `options.filename` (`string`): defines the output filename of the SourceMap. If no value is provided the source map is inlined. -* `options.append` (`string`): is appended to the original asset. Usually the `#sourceMappingURL` comment. `[url]` is replaced with a URL to the source map file. `false` disables the appending. -* `options.moduleFilenameTemplate` / `options.fallbackModuleFilenameTemplate` (`string`): see [`output.devtoolModuleFilenameTemplate`](/configuration/output/#output-devtoolmodulefilenametemplate). -* `options.module` (`boolean`): (defaults to `true`) When `false` loaders do not generate source maps and the transformed code is used as source instead. -* `options.columns` (`boolean`): (defaults to `true`) When `false` column mappings in source maps are ignored and a faster source map implementation is used. -* `options.lineToLine` (`{test: string|RegExp|Array, include: string|RegExp|Array, exclude: string|RegExp|Array}` matched modules uses simple (faster) line to line source mappings. +- `test` (`string|regex|array`): Include source maps for modules based on their extension (defaults to `.js` and `.css`). +- `include` (`string|regex|array`): Include source maps for module paths that match the given value. +- `exclude` (`string|regex|array`): Exclude modules that match the given value from source map generation. +- `filename` (`string`): Defines the output filename of the SourceMap (will be inlined if no value is provided). +- `append` (`string`): Appends the given value to the original asset. Usually the `#sourceMappingURL` comment. `[url]` is replaced with a URL to the source map file. `false` disables the appending. +- `moduleFilenameTemplate` (`string`): See [`output.devtoolModuleFilenameTemplate`](/configuration/output/#output-devtoolmodulefilenametemplate). +- `fallbackModuleFilenameTemplate` (`string`): See link above. +- `module` (`boolean`): Indicates whether loaders should generate source maps (defaults to `true`). +- `columns` (`boolean`): Indicates whether column mappings should be used (defaults to `true`). +- `lineToLine` (`object`): Simplify and speed up source mapping by using line to line source mappings for matched modules.** + +The `lineToLine` object allows for the same `test`, `include`, and `exclude` options described above. + +T> Setting `module` and/or `columns` to `false` will yield less accurate source maps but will also improve compilation performance significantly. ## Usage: Exclude Vendor Maps From a26cc705478c6988822da50a6403ea5582f1d190 Mon Sep 17 00:00:00 2001 From: Pablo Morra Date: Sun, 10 Sep 2017 00:30:15 -0300 Subject: [PATCH 03/22] docs(guides): update "external limitations" example in author-libraries (#1583) --- src/content/guides/author-libraries.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/guides/author-libraries.md b/src/content/guides/author-libraries.md index c0c8e159fcb5..b859872fa7fe 100644 --- a/src/content/guides/author-libraries.md +++ b/src/content/guides/author-libraries.md @@ -194,8 +194,8 @@ T> Note that if you only plan on using your library as a dependency in another w For libraries that use several files from a dependency: ``` js -import A from 'dependency/one'; -import B from 'dependency/two'; +import A from 'library/one'; +import B from 'library/two'; // ... ``` From 287e0e1f0ddfb85896ab795671e69cb53f0d1568 Mon Sep 17 00:00:00 2001 From: Lior Greenberg Date: Sun, 10 Sep 2017 06:35:53 +0300 Subject: [PATCH 04/22] docs(plugins): update commons-chunk-plugin.md (#1560) Changed example to declare the plugin within `plugins` property. --- src/content/plugins/commons-chunk-plugin.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/content/plugins/commons-chunk-plugin.md b/src/content/plugins/commons-chunk-plugin.md index cf61f333c91c..19e62658e5cc 100644 --- a/src/content/plugins/commons-chunk-plugin.md +++ b/src/content/plugins/commons-chunk-plugin.md @@ -98,17 +98,18 @@ Split your code into vendor and application. entry: { vendor: ["jquery", "other-lib"], app: "./entry" -} -new webpack.optimize.CommonsChunkPlugin({ - name: "vendor", - - // filename: "vendor.js" - // (Give the chunk a different name) +}, +plugins: [ + new webpack.optimize.CommonsChunkPlugin({ + name: "vendor", + // filename: "vendor.js" + // (Give the chunk a different name) - minChunks: Infinity, - // (with more entries, this ensures that no other module - // goes into the vendor chunk) -}) + minChunks: Infinity, + // (with more entries, this ensures that no other module + // goes into the vendor chunk) + }) +] ``` ```html From e8dc2f30e28d323cb05c76eebd068fe9ac340b3e Mon Sep 17 00:00:00 2001 From: Greg Venech Date: Mon, 11 Sep 2017 20:55:50 -0400 Subject: [PATCH 05/22] docs(guides): rewrite shimming (#1579) Rewrite the main sections of the guide to synchronize it with the other core guides. Briefly mention the other utilities that don't require full on examples (details can be found via links). Closes #1258 --- src/content/guides/shimming.md | 493 +++++++++++++++++++++++---------- 1 file changed, 347 insertions(+), 146 deletions(-) diff --git a/src/content/guides/shimming.md b/src/content/guides/shimming.md index 2976c0dcc40c..e3c42c159986 100644 --- a/src/content/guides/shimming.md +++ b/src/content/guides/shimming.md @@ -13,233 +13,434 @@ related: url: https://github.com/babel/babel-preset-env#usebuiltins --- -`webpack` as a module bundler can understand modules written as ES2015 modules, CommonJS or AMD. But many times, while using third party libraries, we see that they expect dependencies which are global, AKA `$` for `jquery`. They might also be creating global variables which need to be exported. Here we will see different ways to help webpack understand these __broken modules__. +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. -## Prefer unminified CommonJS/AMD files over bundled `dist` versions. +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 patch (i.e. load them on demand). -Most modules link the `dist` version in the `main` field of their `package.json`. While this is useful for most developers, for webpack it is better to alias the src version because this way webpack is able to optimize dependencies better. However in most cases `dist` works fine as well. +The following article will walk through both of these use cases. -``` javascript -// webpack.config.js +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. -module.exports = { - ... - resolve: { - alias: { - jquery: "jquery/src/jquery" - } - } -}; + +## 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`. -## `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: -The [`ProvidePlugin`](/plugins/provide-plugin) makes a module available as a variable in every other module required by `webpack`. The module is required only if you use the variable. -Most legacy modules rely on the presence of specific globals, like jQuery plugins do on `$` or `jQuery`. In this scenario, you can configure webpack to prepend `var $ = require(“jquery”)` every time it encounters the global `$` identifier. +__src/index.js__ -```javascript -module.exports = { - plugins: [ - new webpack.ProvidePlugin({ - $: 'jquery', - jQuery: 'jquery' - }) - ] -}; +``` 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()); ``` -This plugin is also capable of providing only a certain export of a module by configuring it with an array path using this format: `[module, child, ...children?]`. +__webpack.config.js__ -The following configuration will correctly import function `__assign` from TypeScript's `tslib` package, and provide it wherever it's invoked. +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') +- } ++ }, ++ plugins: [ ++ new webpack.ProvidePlugin({ ++ lodash: 'lodash' ++ }) ++ ] + }; +``` -```javascript -module.exports = { - plugins: [ - new webpack.ProvidePlugin({ - __assign: ['tslib', '__assign'], - __extends: ['tslib', '__extends'], - }) - ] -}; +What we've essentially done here is tell webpack... + +> If you encounter at least one instance of the variable `lodash`, 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 +TODO: Include output ``` +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: -## `imports-loader` +__src/index.js__ -[`imports-loader`](/loaders/imports-loader/) inserts necessary globals into the required legacy module. -For example, Some legacy modules rely on `this` being the `window` object. This becomes a problem when the module is executed in a CommonJS context where `this` equals `module.exports`. In this case you can override `this` using the `imports-loader`. +``` diff + function component() { + var element = document.createElement('div'); -__webpack.config.js__ +- element.innerHTML = _.join(['Hello', 'webpack'], ' '); ++ element.innerHTML = join(['Hello', 'webpack'], ' '); -```javascript -module.exports = { - module: { - rules: [{ - test: require.resolve("some-module"), - use: 'imports-loader?this=>window' - }] + return element; } -}; -``` -There are modules that support different [module styles](/concepts/modules), like AMD, CommonJS and legacy. However, most of the time 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`: + document.body.appendChild(component()); +``` __webpack.config.js__ -```javascript -module.exports = { - module: { - rules: [{ - test: require.resolve("some-module"), - use: 'imports-loader?define=>false' - }] - } -}; +``` diff + const path = require('path'); + + module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + plugins: [ + new webpack.ProvidePlugin({ +- lodash: 'lodash' ++ join: ['lodash', 'join'] + }) + ] + }; ``` +This would go nicely with [Tree Shaking](/guides/tree-shaking) as the rest of the `lodash` library should get dropped. -## `exports-loader` -Let's say a library creates a global variable that it expects its consumers to use; In this case, we can use [`exports-loader`](/loaders/exports-loader/), to export that global variable in CommonJS format. For instance, in order to export `file` as `file` and `helpers.parse` as `parse`: +## Granular Shimming -__webpack.config.js__ +Some legacy modules rely on `this` being the `window` object. Let's update our `index.js` so this is the case: -```javascript -module.exports = { - module: { - rules: [{ - test: require.resolve("some-module"), - use: 'exports-loader?file,parse=helpers.parse' - // adds below code the file's source: - // exports["file"] = file; - // exports["parse"] = helpers.parse; - }] +``` 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/): -## `script-loader` +__webpack.config.js__ -The [`script-loader`](/loaders/script-loader/) evaluates code in the global context, just like you would add the code into a `script` tag. In this mode, every normal library should work. `require`, `module`, etc. are undefined. +``` diff + const path = require('path'); + + 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'] + }) + ] + }; +``` -W> The file is added as string to the bundle. It is not minimized by `webpack`, so use a minimized version. There is also no dev tool support for libraries added by this loader. -Assuming you have a `legacy.js` file containing … +## Global Exports -```javascript -GLOBAL_CONFIG = {}; +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 ``` -… using the `script-loader` … +__src/globals.js__ -```javascript -require('script-loader!legacy.js'); +``` js +var file = 'blah.txt'; +var helpers = { + test: function() { console.log('test something'); }, + parse: function() { console.log('parse something'); } +} ``` -… basically yields: +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`: -```javascript -eval("GLOBAL_CONFIG = {};"); +__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: 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. -## `noParse` option -When there is no AMD/CommonJS version of the module and you want to include the `dist`, you can flag this module as [`noParse`](/configuration/module/#module-noparse). Then `webpack` will just include the module without parsing it, which can be used to improve the build time. +## Loading Polyfills -W> Any feature requiring the AST, like the `ProvidePlugin`, will not work. +Almost everything we've discussed thus far has been in relation to handling legacy packages. Let's move on to our second topic: __polyfills__. -```javascript -module.exports = { - module: { - noParse: /jquery|backbone/ +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 i --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. -## Node Built-Ins +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. -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. +Let's move our `import` to a new file and add the [`whatwg-fetch`](https://github.com/github/fetch) polyfill: +``` bash +npm i --save whatwg-fetch +``` -## Loading polyfills on demand +__src/index.js__ -It's common in web projects to include polyfills in the main bundle. This is not recommended because we are penalizing modern browsers users by making them download a bigger file with unneeded scripts. +``` diff +- import 'babel-polyfill'; +- + function component() { + var element = document.createElement('div'); -The simplest way to mitigate this is by adding a separate entry point in your webpack config file including the polyfills your project needs. + element.innerHTML = join(['Hello', 'webpack'], ' '); -```javascript -// webpack.config.js -module.exports = { - entry: { - polyfills: [ - 'babel-polyfill', - 'whatwg-fetch' - ], - main: './src/index.js' + return element; } - // ... rest of your webpack config -}; + + document.body.appendChild(component()); ``` -An alternative is to create a new entry file and manually import these packages. +__project__ + +``` diff + webpack-demo + |- package.json + |- webpack.config.js + |- /dist + |- /src + |- index.js + |- globals.js ++ |- polyfills.js + |- /node_modules +``` + +__src/polyfills.js__ ```javascript -// src/polyfills.js import 'babel-polyfill'; import 'whatwg-fetch'; ``` -```javascript -// webpack.config.js -module.exports = { - entry: { - polyfills: './src/polyfills.js', - main: './src/index.js' - } - // rest of your webpack config -}; +__webpack.config.js__ + +``` diff + const path = require('path'); + + 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'] + }) + ] + }; ``` -In your html file you need to conditionally load the `polyfills.js` file before your bundle. How you make this decision depends on the technologies and browsers you need to support. +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 + + + Getting Started ++ + + + + + +``` + +Now we can `fetch` some data within our entry script: + +__src/index.js__ -```html - + 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)) ``` -T> Any script added dynamically like in the example above will run as soon as it's parsed, but we need our polyfill to run before our bundle. This is why we are setting `async` to `false` for each script. +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. -### Smaller babel polyfill +## Further Optimizations -`babel-preset-env` uses [browserslist](https://github.com/ai/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the `useBuiltIns` option _(false by default)_ which converts your global `babel-polyfill` import to a more granular feature by feature import pattern like: +The `babel-preset-env` package uses [browserslist](https://github.com/ai/browserslist) to transpile only what is not supported in your browsers matrix. This preset comes with the `useBuiltIns` option, `false` by default, which converts your global `babel-polyfill` import to a more granular feature by feature `import` pattern: -```javascript -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"; +``` 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 different [module styles](/concepts/modules) like 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/). From 2caa06a5ba47ad7532304da2b9b16936dded6069 Mon Sep 17 00:00:00 2001 From: Jeremias Menichelli Date: Tue, 12 Sep 2017 22:52:29 -0300 Subject: [PATCH 06/22] docs(guides): fix small issues in shimming (#1591) --- src/content/guides/shimming.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/guides/shimming.md b/src/content/guides/shimming.md index e3c42c159986..de9f66152a81 100644 --- a/src/content/guides/shimming.md +++ b/src/content/guides/shimming.md @@ -17,7 +17,7 @@ The `webpack` compiler can understand modules written as ES2015 modules, CommonJ 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 patch (i.e. load them on demand). +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. @@ -379,7 +379,7 @@ __dist/index.html__ + - + ``` From ddaf6845bc2deac5128ace31314e16e5d2ff9e4f Mon Sep 17 00:00:00 2001 From: ltaloc Date: Wed, 13 Sep 2017 02:53:28 +0100 Subject: [PATCH 07/22] docs(guides): fix entry path in typescript (#1592) --- src/content/guides/typescript.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/guides/typescript.md b/src/content/guides/typescript.md index 684f8d6bab8c..395f93fdc616 100644 --- a/src/content/guides/typescript.md +++ b/src/content/guides/typescript.md @@ -67,7 +67,7 @@ __webpack.config.js__ const path = require('path'); module.exports = { - entry: './index.ts', + entry: './src/index.ts', module: { rules: [ { @@ -127,7 +127,7 @@ __webpack.config.js__ const path = require('path'); module.exports = { - entry: './index.ts', + entry: './src/index.ts', + devtool: 'inline-source-map', module: { rules: [ From 28ac2fd30af5a8ddd86945eeaa732069f1ff76e4 Mon Sep 17 00:00:00 2001 From: Elliot Waite Date: Tue, 12 Sep 2017 18:54:03 -0700 Subject: [PATCH 08/22] docs(guides): fix typos in production (#1584) --- src/content/guides/production.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/guides/production.md b/src/content/guides/production.md index 5c0f1421f49c..e2f5189077ee 100644 --- a/src/content/guides/production.md +++ b/src/content/guides/production.md @@ -26,7 +26,7 @@ The goals of _development_ and _production_ builds differ greatly. In _developme 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 work on in previous guides: +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 @@ -145,7 +145,7 @@ Feel free to run those scripts and see how the output changes as we continue add ## Minification -Note that while the [`UglifyJSPlugin`](/plugins/uglifyjs-webpack-plugin) is a great place to start for minification, there are other options out there. Here's a few more popular ones: +Note that while the [`UglifyJSPlugin`](/plugins/uglifyjs-webpack-plugin) is a great place to start for minification, 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) @@ -232,6 +232,6 @@ __src/index.js__ ## CLI Alternatives -Some of what has been described above is also achievable via the command line. For example, the `--optimize-minize` flag will include the `UglifyJSPlugin` 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 include invoke both those flags and thus the plugins to be included. +Some of what has been described above is also achievable via the command line. For example, the `--optimize-minize` flag will include the `UglifyJSPlugin` 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. From 2ff84b97f98c8907e669de36c2936924bc861472 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 13 Sep 2017 14:49:26 +0200 Subject: [PATCH 09/22] fix(sponsors): update to reflect opencollective change (#1588) OpenCollective's structure changed a bit. This address that and makes a few other notable changes: - add additional sponsors - allow to merge additional sponsors to existing sponsors - limit width of logos to 3 x height to disallow very wide logos - format money values with commas --- .gitignore | 3 +- src/components/Splash/Splash.jsx | 10 +-- src/components/Support/Support.jsx | 58 +++++++++++++----- src/components/Support/Support.scss | 31 +++++----- .../Support/assets/segment-logo.png | Bin 0 -> 18106 bytes src/components/Support/support-additional.js | 38 ++++++++++++ .../Support/support-additional.json | 23 ------- src/scripts/fetch_supporters.js | 24 ++++++++ 8 files changed, 128 insertions(+), 59 deletions(-) create mode 100644 src/components/Support/assets/segment-logo.png create mode 100644 src/components/Support/support-additional.js delete mode 100644 src/components/Support/support-additional.json diff --git a/.gitignore b/.gitignore index c098e893f9fc..5570874da45d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ node_modules npm-debug.log build generated -support-backers.json -support-sponsors.json +support-*.json starter-kits-data.json .antwar diff --git a/src/components/Splash/Splash.jsx b/src/components/Splash/Splash.jsx index d31214203c82..f41e2ec30dbc 100644 --- a/src/components/Splash/Splash.jsx +++ b/src/components/Splash/Splash.jsx @@ -29,19 +29,19 @@ const Splash = () => (

Through contributions, donations, and sponsorship, you allow webpack to thrive. Your donations directly support office hours, continued enhancements, and most importantly, great documentation and learning material!

Platinum Sponsors

- +

Gold Sponsors

- +

Silver Sponsors

- +

Bronze Sponsors

- +

Backers

- + diff --git a/src/components/Support/Support.jsx b/src/components/Support/Support.jsx index e43777d2b3dd..2890af4772c5 100644 --- a/src/components/Support/Support.jsx +++ b/src/components/Support/Support.jsx @@ -1,9 +1,17 @@ import React from 'react'; -import Additional from './support-additional.json'; +import GoldSponsors from './support-goldsponsors.json'; +import SilverSponsors from './support-silversponsors.json'; +import Sponsors from './support-sponsors.json'; +import Backers from './support-backers.json'; +import Additional from './support-additional.js'; import './Support.scss'; const ranks = { + backer: { + maximum: 200 + }, bronze: { + minimum: 200, maximum: 2000 }, silver: { @@ -19,17 +27,37 @@ const ranks = { } }; +function formatMoney(number) { + let str = Math.round(number) + ''; + if (str.length > 3) { + str = str.substr(0, str.length - 3) + ',' + str.substr(-3); + } + return str; +} + export default class Support extends React.Component { render() { - let { rank, type } = this.props; - let supporters = require(`./support-${type}.json`); + let { rank } = this.props; + let supporters = [ + ...GoldSponsors, + ...SilverSponsors, + ...Sponsors, + ...Backers, + ]; - if (type === 'sponsors') { - supporters = supporters.slice(); - supporters.push(...Additional); - supporters.sort((a, b) => b.totalDonations - a.totalDonations); + // merge or add additional backers/sponsors + for(const additional of Additional) { + const existing = supporters.find(supporter => supporter.username && supporter.username === additional.username); + if (existing) { + existing.totalDonations += additional.totalDonations; + } else { + supporters.push(additional); + } } + // resort list + supporters.sort((a, b) => b.totalDonations - a.totalDonations); + let minimum, maximum; if (rank && ranks[rank]) { @@ -48,14 +76,14 @@ export default class Support extends React.Component { return (
- { type === 'sponsors' ? ( + { rank === 'backer' ? (

- { rank } sponsors - are those who have pledged { minimum ? `$${minimum}` : 'up' } { maximum ? `to $${maximum}` : 'or more' } to webpack. + The following Backers are individuals who have contributed various amounts of money in order to help support webpack. Every little bit helps, and we appreciate even the smallest contributions.

) : (

- The following Backers are individuals who have contributed various amounts of money in order to help support webpack. Every little bit helps, and we appreciate even the smallest contributions. + { rank } sponsors + are those who have pledged { minimum ? `$${formatMoney(minimum)}` : 'up' } { maximum ? `to $${formatMoney(maximum)}` : 'or more' } to webpack.

)}
@@ -64,22 +92,22 @@ export default class Support extends React.Component { supporters.map((supporter, index) => ( { supporter.avatar ? { : supporter.name } - { type === 'backers' ?
: null } + { rank === 'backer' ?
: null } )) }
diff --git a/src/components/Support/Support.scss b/src/components/Support/Support.scss index ce649015ec8e..476abccdbac4 100644 --- a/src/components/Support/Support.scss +++ b/src/components/Support/Support.scss @@ -22,22 +22,25 @@ margin: 0 2px 2px 2px; } - &__sponsors-avatar { - &-bronze, &-normal { - height: 32px; - } - &-silver { - height: 64px; - } - &-gold { - height: 96px; - } - &-platinum { - height: 128px; - } + &__bronze-avatar { + height: 32px; + max-width: 96px; + } + + &__silver-avatar { + height: 64px; + max-width: 192px; + } + + &__gold-avatar { + height: 96px; + } + + &__platinum-avatar { + height: 128px; } - &__backers-avatar-normal { + &__backer-avatar { width: 31px; height: 31px; border-radius: 50%; diff --git a/src/components/Support/assets/segment-logo.png b/src/components/Support/assets/segment-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..33552ece113aca4a387a1f6f9054e44c70af5bf6 GIT binary patch literal 18106 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

OA0RL*}X~}wRpvqvN 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 literal 0 HcmV?d00001 diff --git a/src/components/Support/support-additional.js b/src/components/Support/support-additional.js new file mode 100644 index 000000000000..3595290bc823 --- /dev/null +++ b/src/components/Support/support-additional.js @@ -0,0 +1,38 @@ +export default [ + { + name: "MoonMail", + avatar: "https://static.moonmail.io/moonmail-logo.svg", + website: "https://moonmail.io/?utm_source=webpack.js.org", + totalDonations: 11000, + reason: "Paypal" + }, + { + name: "Google Angular", + avatar: "https://res.cloudinary.com/opencollective/image/upload/v1485288529/angular_uxllte.png", + website: "https://angular.io/?utm_source=webpack&utm_medium=documentation&utm_campaign=sponsorship", + totalDonations: 250000, + reason: "Paypal" + }, + { + name: "Architects.io", + avatar: null, + website: "http://architects.io/?utm_source=webpack&utm_medium=documentation&utm_campaign=sponsorship", + totalDonations: 30000, + reason: "Paypal" + }, + { + username: "peerigon", + name: "Peerigon", + avatar: "https://opencollective-production.s3-us-west-1.amazonaws.com/e8a1de10-99c8-11e6-8650-f92e594d5de8.png", + website: "https://peerigon.com/?utm_source=webpack&utm_medium=documentation&utm_campaign=sponsorship", + totalDonations: 144139, + reason: "webpack meetup 2017-07" + }, + { + name: "Segment", + avatar: require("./assets/segment-logo.png"), + website: "https://segment.com/?utm_source=webpack&utm_medium=documentation&utm_campaign=sponsorship", + totalDonations: 1200000, + reason: "Sponsorship 2017-07 - 2017-09" + } +]; diff --git a/src/components/Support/support-additional.json b/src/components/Support/support-additional.json deleted file mode 100644 index b4f5ffcefcaf..000000000000 --- a/src/components/Support/support-additional.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "name": "MoonMail", - "tier": "sponsor", - "avatar": "https://static.moonmail.io/moonmail-logo.svg", - "website": "https://moonmail.io/?utm_source=webpack.js.org", - "totalDonations": 11000 - }, - { - "name": "Google Angular", - "tier": "sponsor", - "avatar": "https://res.cloudinary.com/opencollective/image/upload/v1485288529/angular_uxllte.png", - "website": "https://angular.io/", - "totalDonations": 250000 - }, - { - "name": "Architects.io", - "tier": "sponsor", - "avatar": null, - "website": "http://architects.io/", - "totalDonations": 30000 - } -] diff --git a/src/scripts/fetch_supporters.js b/src/scripts/fetch_supporters.js index 46557b391c45..7b052cc40eb5 100644 --- a/src/scripts/fetch_supporters.js +++ b/src/scripts/fetch_supporters.js @@ -2,6 +2,30 @@ const fs = require('fs'); const request = require('request'); +request('https://opencollective.com/webpack/goldsponsors.json?requireActive=false', (err, response, body) => { + if (err) { + console.error('Failed to fetch goldsponsors: ', err); + + } fs.writeFile('./src/components/Support/support-goldsponsors.json', body, err => { + if (err) { + console.error('Failed to write goldsponsors file: ', err); + + } else console.log('Fetched 1 file: support-goldsponsors.json'); + }); +}); + +request('https://opencollective.com/webpack/silversponsors.json?requireActive=false', (err, response, body) => { + if (err) { + console.error('Failed to fetch silversponsors: ', err); + + } fs.writeFile('./src/components/Support/support-silversponsors.json', body, err => { + if (err) { + console.error('Failed to write silversponsors file: ', err); + + } else console.log('Fetched 1 file: support-silversponsors.json'); + }); +}); + request('https://opencollective.com/webpack/sponsors.json?requireActive=false', (err, response, body) => { if (err) { console.error('Failed to fetch sponsors: ', err); From cb9a035aa04070347423841a540aa0242a3103e8 Mon Sep 17 00:00:00 2001 From: Peter Blazejewicz Date: Thu, 14 Sep 2017 05:56:25 +0200 Subject: [PATCH 10/22] docs(config): update configuration-languages (#1590) Remove local type def from TypeScript snippet. The @types/node type definition module already declares `__dirname` type: https://git.io/v5Dr9 --- src/content/configuration/configuration-languages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/configuration/configuration-languages.md b/src/content/configuration/configuration-languages.md index dcd136f88099..173f7981757c 100644 --- a/src/content/configuration/configuration-languages.md +++ b/src/content/configuration/configuration-languages.md @@ -6,6 +6,7 @@ contributors: - skipjack - tarang9211 - simon04 + - peterblazejewicz --- 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. @@ -26,7 +27,6 @@ __webpack.config.ts__ ```typescript import * as webpack from 'webpack'; import * as path from 'path'; -declare var __dirname; const config: webpack.Configuration = { entry: './foo.js', From bee0f3e7a44fd403c01a60953a778c84d7d72db3 Mon Sep 17 00:00:00 2001 From: Bryan Wain Date: Wed, 13 Sep 2017 22:58:59 -0500 Subject: [PATCH 11/22] docs(guides): update hot-module-replacement (#1539) Add an example to demonstrate using hot module replacement with `webpack-dev-server`'s Node.js API instead of within a normal configuration file. --- src/content/guides/hot-module-replacement.md | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/content/guides/hot-module-replacement.md b/src/content/guides/hot-module-replacement.md index b44c0fe21d83..63607199f232 100644 --- a/src/content/guides/hot-module-replacement.md +++ b/src/content/guides/hot-module-replacement.md @@ -12,6 +12,7 @@ contributors: - skipjack - sbaidon - gdi2290 + - bdwain related: - title: Concepts - Hot Module Replacement url: /concepts/hot-module-replacement @@ -126,6 +127,36 @@ main.js:4395 [WDS] Hot Module Replacement enabled. ``` +## 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 +}; + +webpackDevServer.addDevServerEntrypoints(config, options); +const compiler = webpack(config); +const server = new webpackDevServer(compiler, options); + +server.listen(5000, () => { + console.log('dev server listening on port 5000'); +}); +``` + + ## 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. From 2af6968700514a3647d1797dbf7371a60de26e6d Mon Sep 17 00:00:00 2001 From: Marcus Molchany Date: Wed, 13 Sep 2017 21:14:17 -0700 Subject: [PATCH 12/22] docs(guides): update development.md (#1586) The article was missing references to `clean-webpack-plugin` in the `webpack.config.js` file and `package.json` files. --- src/content/guides/development.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/content/guides/development.md b/src/content/guides/development.md index 7d14c3f59687..68e30beceae5 100644 --- a/src/content/guides/development.md +++ b/src/content/guides/development.md @@ -131,6 +131,7 @@ __package.json__ "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", @@ -175,6 +176,7 @@ __webpack.config.js__ ``` diff const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); + const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = { entry: { @@ -220,6 +222,7 @@ __package.json__ "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", @@ -337,6 +340,7 @@ __package.json__ "author": "", "license": "ISC", "devDependencies": { + "clean-webpack-plugin": "^0.1.16", "css-loader": "^0.28.4", "csv-loader": "^2.1.1", "express": "^4.15.3", From 5f6a75ecdc3e6a7a49eb73354a19e6eb6b7fa7f8 Mon Sep 17 00:00:00 2001 From: MijaelWatts Date: Wed, 13 Sep 2017 23:15:46 -0500 Subject: [PATCH 13/22] docs(guides): update tree-shaking.md (#1589) As a conclusion, I thought it would be a good idea to show case a high-level explanation of why it's called tree shaking. Once the user reads the guide and ends up with a high-level explanation the word tree shaking will stick to the user's head. --- src/content/guides/tree-shaking.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/content/guides/tree-shaking.md b/src/content/guides/tree-shaking.md index 62d69b5842cd..4091cac19b05 100644 --- a/src/content/guides/tree-shaking.md +++ b/src/content/guides/tree-shaking.md @@ -6,6 +6,7 @@ contributors: - zacanger - alexjoverm - avant1 + - MijaelWatts related: - title: Tree shaking with webpack 2, TypeScript and Babel url: https://alexjoverm.github.io/2017/03/06/Tree-shaking-with-Webpack-2-TypeScript-and-Babel/ @@ -146,4 +147,6 @@ So, what we've learned is that in order to take advantage of _tree shaking_, you - Use ES2015 module syntax (i.e. `import` and `export`). - Include a minifier that supports dead code removal (e.g. the `UglifyJSPlugin`). +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 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). From 3dc7e7403ecb8e9a3987fc57d9ce02499514b9fb Mon Sep 17 00:00:00 2001 From: Diego Faria Date: Thu, 14 Sep 2017 06:23:56 +0200 Subject: [PATCH 14/22] docs(guides): update code-splitting (#1585) Suggest solutions to the problem right away seems to be a better approach. Use similar text as was used here: https://webpack.js.org/api/module-methods/#import- --- src/content/guides/code-splitting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/guides/code-splitting.md b/src/content/guides/code-splitting.md index 69ef43ff0019..4984f0bbbdb5 100644 --- a/src/content/guides/code-splitting.md +++ b/src/content/guides/code-splitting.md @@ -170,7 +170,7 @@ T> The [`CommonsChunkPlugin`](/plugins/commons-chunk-plugin) is also used to spl Two similar techniques are supported by webpack when it comes to dynamic code splitting. The first and more preferable approach is use to 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). If you want to support older browsers that lack `Promise` support (e.g. Internet Explorer), you'll need to include a `Promise` polyfill _before_ your primary bundles. +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 [`CommonsChunkPlugin`](/plugins/commons-chunk-plugin) from our config as they won't be needed for this next demonstration: From 5003179ac3d12c4db01ba00c43a80172b8c39914 Mon Sep 17 00:00:00 2001 From: Phips Peter Date: Thu, 14 Sep 2017 19:44:54 -0700 Subject: [PATCH 15/22] docs(plugins): update module-concatenation-plugin (#1565) Add more information about optimization bailouts. Attempt to transfer content from the blog post to the official docs. I want to follow up with a PR for better bailout reasons. The hope is that the reasons will match those listed in the table. --- .../plugins/module-concatenation-plugin.md | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/content/plugins/module-concatenation-plugin.md b/src/content/plugins/module-concatenation-plugin.md index 06a6bf0bf9ba..f3d52b691858 100644 --- a/src/content/plugins/module-concatenation-plugin.md +++ b/src/content/plugins/module-concatenation-plugin.md @@ -16,3 +16,81 @@ new webpack.optimize.ModuleConcatenationPlugin() ``` > Scope Hoisting is specifically a feature made possible by ECMAScript Module syntax. Because of this webpack may fallback to normal bundling based on what kind of modules you are using, and [other conditions](https://medium.com/webpack/webpack-freelancing-log-book-week-5-7-4764be3266f5). + + +## Optimization Bailouts + +As the article explains, webpack attempts to achieve partial scope hoisting. It will merge modules into a single scope but cannot do so in every case. If webpack cannot merge a module, the two alternatives are Prevent and Root. Prevent means the module must be in its own scope. Root means a new module group will be created. The following conditions determine the outcome: + +Condition | Outcome +--------------------------------------------- | -------- +Non ES6 Module | Prevent +Imported By Non Import | Root +Imported From Other Chunk | Root +Imported By Multiple Other Module Groups | Root +Imported With `import()` | Root +Affected By `ProvidePlugin` Or Using `module` | Prevent +HMR Accepted | Root +Using `eval()` | Prevent +In Multiple Chunks | Prevent +`export * from "cjs-module"` | Prevent + + +### Module Grouping Algorithm + +The following pseudo JavaScript explains the algorithm: + +```js +modules.forEach(module => { + const group = new ModuleGroup({ + root: module + }); + module.dependencies.forEach(dependency => { + tryToAdd(group, dependency); + }); + if (group.modules.length > 1) { + orderedModules = topologicalSort(group.modules); + concatenatedModule = new ConcatenatedModule(orderedModules); + chunk.add(concatenatedModule); + orderedModules.forEach(groupModule => { + chunk.remove(groupModule); + }); + } +}); + +function tryToAdd(group, module) { + if (group.has(module)) { + return true; + } + if (!hasPreconditions(module)) { + return false; + } + const nextGroup = group; + const result = module.dependents.reduce((check, dependent) => { + return check && tryToAdd(nextGroup, dependent); + }, true); + if (!result) { + return false; + } + module.dependencies.forEach(depenency => { + tryToAdd(group, depenency); + }); + group.merge(nextGroup); + return true; +} +``` + + +### Debugging Optimization Bailouts + +When using the webpack CLI, the `--display-optimization-bailout` flag will display bailout reasons. When using the webpack config, just add the following to the `stats` object: + +```js +{ + ...stats, + // Examine all modules + maxModules: Infinity, + // Display bailout reasons + optimizationBailout: true +} +``` From 60f2679e221c670f3fa941a32c341f77bc48bf29 Mon Sep 17 00:00:00 2001 From: Rodolfo Rodriguez Date: Mon, 18 Sep 2017 16:05:03 -0500 Subject: [PATCH 16/22] docs(api): fix type in compiler.md (#1601) --- src/content/api/plugins/compiler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/api/plugins/compiler.md b/src/content/api/plugins/compiler.md index bc27dc66a226..98557eff1b31 100644 --- a/src/content/api/plugins/compiler.md +++ b/src/content/api/plugins/compiler.md @@ -27,7 +27,7 @@ compiler.options = {...}; class LogPlugin { apply (compiler) { compiler.plugin('should-emit', compilation => { - console.log('should i emit?'); + console.log('should I emit?'); return true; }) } From eecdc8d4027d9eb0d115c9ba6f325fbfe14fe1b4 Mon Sep 17 00:00:00 2001 From: Tommy Yu Date: Tue, 19 Sep 2017 10:42:45 +1200 Subject: [PATCH 17/22] docs(config): update output.md (#1541) Clarify interactions between `libraryTarget` and `library`. The interactions between the two and how some of the sections were not well explained, in some cases were incorrect, misleading or missing information. --- src/content/configuration/output.md | 169 ++++++++++++++++++---------- 1 file changed, 112 insertions(+), 57 deletions(-) diff --git a/src/content/configuration/output.md b/src/content/configuration/output.md index 09cf6bcd75f4..1534009d8a06 100644 --- a/src/content/configuration/output.md +++ b/src/content/configuration/output.md @@ -18,7 +18,7 @@ The top-level `output` key contains set of options instructing webpack on how an `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, simply set `auxiliaryComment` to a string: +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: ``` js output: { @@ -293,15 +293,15 @@ If using the [`output.library`](#output-library) option, the library name is aut `string` or `object` (since webpack 3.1.0; for `libraryTarget: "umd"`) -Use `library`, and `libraryTarget` below, when writing a JavaScript library that should export values, which can be used by other code depending on it. Pass a string with the name of the library: +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: -``` js -library: "MyLibrary" +```javascript +output: { + library: "MyLibrary" +} ``` -The name is used depending on the value of the [`output.libraryTarget`](#output-librarytarget) options. - -Note that `output.libraryTarget` defaults to `var`. This means if only `output.library` is used it is exported as variable declaration (when used as script tag it's available in the global scope after execution). +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. T> Read the [authoring libraries guide](/guides/author-libraries) guide for more information on `output.library` as well as `output.libraryTarget`. @@ -325,117 +325,134 @@ The following configurations are supported: ```javascript // if your entry has a default export of `MyDefaultModule` var MyDefaultModule = _entry_return_.default; - -// your users will use your library like: -MyDefaultModule.doSomething(); ``` `libraryExport: "MyModule"` - The **specified module** will be assigned to the library target: ```javascript -// if your entry exports a module `MyModule` var MyModule = _entry_return_.MyModule; - -// your users will use your library like: -MyModule.doSomething(); ``` `libraryExport: ["MyModule", "MySubModule"]` - The array is interpreted as a **path to a module** to be assigned to the library target: ```javascript -// if your entry exports `MyModule` which in turn exports `MySubModule` var MySubModule = _entry_return_.MyModule.MySubModule; +``` + +As the examples have shown that the return values of the entry points are bounded to those named variables, the usage of the resulting library is simply like so: +```javascript +MyDefaultModule.doSomething(); +MyModule.doSomething(); MySubModule.doSomething(); ``` - ## `output.libraryTarget` `string` > Default: `"var"` -Configure how the library will be exposed. Any one of the following options can be used. +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 -The following options are supported: +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_; -// your users will use your library like: +// In a separate script... MyLibrary.doSomething(); ``` -W> Not specifying a `output.library` will cancel this `"var"` configuration. +W> When using this option, an empty `output.library` will result in no assignment. -`libraryTarget: "this"` - When your library is loaded, the **return value of your entry point** will be assigned to this, the meaning of `this` is up to you: +`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_; -// your users will use your library like: +// In a separate script... this.MyLibrary.doSomething(); -MyLibrary.doSomething(); //if this is window +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. -`libraryTarget: "window"` - When your library is loaded, **the return value of your entry point** will be part `window` object. - - ```javascript - window["MyLibrary"] = _entry_return_; +```javascript +window["MyLibrary"] = _entry_return_; -//your users will use your library like: window.MyLibrary.doSomething(); - ``` +``` -`libraryTarget: "global"` - When your library is loaded, **the return value of your entry point** will be part `global` object. +`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_; +```javascript +global["MyLibrary"] = _entry_return_; -//your users will use your library like: global.MyLibrary.doSomething(); - ``` +``` -`libraryTarget: "commonjs"` - When your library is loaded, **the return value of your entry point** will be part of the exports object. As the name implies, this is used in CommonJS environments: +`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_; -//your users will use your library like: require("MyLibrary").doSomething(); ``` +### Module Definition Systems -`libraryTarget: "commonjs2"` - When your library is loaded, **the return value of your entry point** will be part of the exports object. As the name implies, this is used in CommonJS environments: +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_; -//your users will use your library like: require("MyLibrary").doSomething(); ``` -T> Wondering the difference between CommonJS and CommonJS2? Check [this](https://github.com/webpack/webpack/issues/1114) out (they are pretty much the same). +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"` - In this case webpack will make your library an AMD module. -Note that your entry chunk must be defined with the `define` property, if not, webpack will create the AMD module, but without dependencies. The output will be something like this: +`libraryTarget: "amd"` - This will expose your library as an AMD module. -```javascript -define([], function() { - // This module returns is what your entry chunk returns -}); -``` - -If you download this script, you may get an error: `define is not defined`, it’s ok! If you are distributing your library with AMD, then your users need to use RequireJS to load it. Once you have RequireJS loaded, you can load your library. +AMD modules require that the entry chunk (e.g. the first script loaded by the `