docs(webpack): copy edits, TOC updates, and fix entry object prose (#3413)

This commit is contained in:
Kapunahele Wong 2017-03-23 18:30:12 -04:00 committed by Ward Bell
parent a5464d45a0
commit 56c8706262

View File

@ -14,24 +14,30 @@ style.
This guide offers a taste of Webpack and explains how to use it with Angular applications. This guide offers a taste of Webpack and explains how to use it with Angular applications.
<a id="top"></a> <a id="top"></a>
## Table of contents # Contents
[What is Webpack?](#what-is-webpack)
* [What is Webpack?](#what-is-webpack)
* [Entries and outputs](#entries-outputs) * [Entries and outputs](#entries-outputs)
* [Multiple bundles](#multiple-bundles)
* [Loaders](#loaders) * [Loaders](#loaders)
* [Plugins](#plugins) * [Plugins](#plugins)
* [Configuring Webpack](#configure-webpack)
[Configuring Webpack](#configure-webpack) * [Polyfills](#polyfills)
* [Common configuration](#common-configuration) * [Common configuration](#common-configuration)
* [Inside `webpack.common.js`](#inside-webpack-commonjs)
- [entry](#common-entries)
- [resolve extension-less imports](#common-resolves)
- [`module.rules`](#common-rules)
- [Plugins](#plugins)
- [`CommonsChunkPlugin`](#commons-chunk-plugin)
- [`HtmlWebpackPlugin`](#html-webpack-plugin)
* [Environment specific configuration](#environment-configuration)
* [Development configuration](#development-configuration) * [Development configuration](#development-configuration)
* [Production configuration](#production-configuration) * [Production configuration](#production-configuration)
* [Test configuration](#test-configuration) * [Test configuration](#test-configuration)
* [Trying it out](#try)
[Trying it out](#try) * [Highlights](#highlights)
* [Conclusion](#conclusion)
[Conclusions](#conclusions)
You can also <a href="/resources/zips/webpack/webpack.zip">download the final result.</a> You can also <a href="/resources/zips/webpack/webpack.zip">download the final result.</a>
@ -41,12 +47,12 @@ style.
## What is Webpack? ## What is Webpack?
Webpack is a powerful module bundler. Webpack is a powerful module bundler.
A _bundle_ is a JavaScript file that incorporate _assets_ that *belong* together and A _bundle_ is a JavaScript file that incorporates _assets_ that *belong* together and
should be served to the client in a response to a single file request. should be served to the client in a response to a single file request.
A bundle can include JavaScript, CSS styles, HTML, and almost any other kind of file. A bundle can include JavaScript, CSS styles, HTML, and almost any other kind of file.
Webpack roams over your application source code, Webpack roams over your application source code,
looking for `import` statements, building a dependency graph, and emitting one (or more) _bundles_. looking for `import` statements, building a dependency graph, and emitting one or more _bundles_.
With plugins and rules, Webpack can preprocess and minify different non-JavaScript files such as TypeScript, SASS, and LESS files. With plugins and rules, Webpack can preprocess and minify different non-JavaScript files such as TypeScript, SASS, and LESS files.
You determine what Webpack does and how it does it with a JavaScript configuration file, `webpack.config.js`. You determine what Webpack does and how it does it with a JavaScript configuration file, `webpack.config.js`.
@ -67,8 +73,8 @@ a(id="entries-outputs")
+makeExample('webpack/ts/src/app/app.component.ts', 'component', 'src/main.ts')(format=".") +makeExample('webpack/ts/src/app/app.component.ts', 'component', 'src/main.ts')(format=".")
:marked :marked
It sees that you're importing *@angular/core* so it adds that to its dependency list for (potential) inclusion in the bundle. It sees that you're importing `@angular/core` so it adds that to its dependency list for potential inclusion in the bundle.
It opens the *@angular/core* file and follows _its_ network of `import` statements until it has built the complete dependency graph from `main.ts` down. It opens the `@angular/core` file and follows _its_ network of `import` statements until it has built the complete dependency graph from `main.ts` down.
Then it **outputs** these files to the `app.js` _bundle file_ designated in configuration: Then it **outputs** these files to the `app.js` _bundle file_ designated in configuration:
@ -82,6 +88,8 @@ a(id="entries-outputs")
This `app.js` output bundle is a single JavaScript file that contains the application source and its dependencies. This `app.js` output bundle is a single JavaScript file that contains the application source and its dependencies.
You'll load it later with a `<script>` tag in the `index.html`. You'll load it later with a `<script>` tag in the `index.html`.
a#multiple-bundles
:marked
#### Multiple bundles #### Multiple bundles
You probably don't want one giant bundle of everything. You probably don't want one giant bundle of everything.
It's preferable to separate the volatile application app code from comparatively stable vendor code modules. It's preferable to separate the volatile application app code from comparatively stable vendor code modules.
@ -120,7 +128,7 @@ a(id="loaders")
:marked :marked
### Loaders ### Loaders
Webpack can bundle any kind of file: JavaScript, TypeScript, CSS, SASS, LESS, images, html, fonts, whatever. Webpack can bundle any kind of file: JavaScript, TypeScript, CSS, SASS, LESS, images, HTML, fonts, whatever.
Webpack _itself_ only understands JavaScript files. Webpack _itself_ only understands JavaScript files.
Teach it to transform non-JavaScript file into their JavaScript equivalents with *loaders*. Teach it to transform non-JavaScript file into their JavaScript equivalents with *loaders*.
Configure loaders for TypeScript and CSS as follows. Configure loaders for TypeScript and CSS as follows.
@ -139,7 +147,8 @@ a(id="loaders")
] ]
:marked :marked
As Webpack encounters `import` statements like these ... When Webpack encounters `import` statements like the following,
it applies the `test` RegEx patterns.
.code-example .code-example
code-example(language="typescript"). code-example(language="typescript").
@ -148,15 +157,15 @@ a(id="loaders")
import 'uiframework/dist/uiframework.css'; import 'uiframework/dist/uiframework.css';
:marked :marked
... it applies the `test` RegEx patterns. When a pattern matches the filename, Webpack processes the file with the associated loader. When a pattern matches the filename, Webpack processes the file with the associated loader.
The first `import` file matches the `.ts` pattern so Webpack processes it with the `awesome-typescript-loader`. The first `import` file matches the `.ts` pattern so Webpack processes it with the `awesome-typescript-loader`.
The imported file doesn't match the second pattern so its loader is ignored. The imported file doesn't match the second pattern so its loader is ignored.
The second `import` matches the second `.css` pattern for which you have *two* loaders chained by the (!) character. The second `import` matches the second `.css` pattern for which you have *two* loaders chained by the (!) character.
Webpack applies chained loaders *right to left* so it applies Webpack applies chained loaders *right to left*. So it applies
the `css` loader first (to flatten CSS `@import` and `url(...)` statements) and the `css` loader first to flatten CSS `@import` and `url(...)` statements.
then the `style` loader (to append the css inside *&lt;style&gt;* elements on the page). Then it applies the `style` loader to append the css inside `<style>` elements on the page.
a(id="plugins") a(id="plugins")
.l-main-section .l-main-section
@ -175,13 +184,13 @@ a(id="plugins")
a(id="configure-webpack") a(id="configure-webpack")
.l-main-section .l-main-section
:marked :marked
## Configure Webpack ## Configuring Webpack
After that brief orientation, you are ready to build your own Webpack configuration for Angular apps. After that brief orientation, you are ready to build your own Webpack configuration for Angular apps.
Begin by setting up the development environment. Begin by setting up the development environment.
Create a **new project folder** Create a new project folder.
code-example(language="sh" class="code-shell"). code-example(language="sh" class="code-shell").
mkdir angular-webpack mkdir angular-webpack
cd angular-webpack cd angular-webpack
@ -205,14 +214,14 @@ code-example(language="sh" class="code-shell").
.l-sub-section .l-sub-section
:marked :marked
Many of these files should be familiar from other Angular documentation guides, Many of these files should be familiar from other Angular documentation guides,
especially the [_Typescript configuration_](../guide/typescript-configuration.html) and especially the [Typescript configuration](../guide/typescript-configuration.html) and
[_npm packages_](../guide/npm-packages.html) guides. [npm packages](../guide/npm-packages.html) guides.
Webpack, the plugins, and the loaders are also installed as packages. Webpack, the plugins, and the loaders are also installed as packages.
They are listed in the updated `packages.json`. They are listed in the updated `packages.json`.
:marked :marked
Open a terminal window and (re)install the *npm* packages Open a terminal window and install the npm packages.
code-example(language="sh" class="code-shell"). code-example(language="sh" class="code-shell").
npm install npm install
@ -222,7 +231,7 @@ a#polyfills
### Polyfills ### Polyfills
You'll need polyfills to run an Angular application in most browsers as explained You'll need polyfills to run an Angular application in most browsers as explained
in the [_Browser Support_](browser-support.html) guide. in the [Browser Support](browser-support.html) guide.
Polyfills should be bundled separately from the application and vendor bundles. Polyfills should be bundled separately from the application and vendor bundles.
Add a `polyfills.ts` like this one to the `src/` folder. Add a `polyfills.ts` like this one to the `src/` folder.
@ -241,7 +250,7 @@ a#polyfills
a(id="common-configuration") a(id="common-configuration")
.l-main-section .l-main-section
:marked :marked
### Common Configuration ### Common configuration
Developers typically have separate configurations for development, production, and test environments. Developers typically have separate configurations for development, production, and test environments.
All three have a lot of configuration in common. All three have a lot of configuration in common.
@ -250,31 +259,32 @@ a(id="common-configuration")
+makeExample('webpack/ts/config/webpack.common.js', null, 'config/webpack.common.js')(format=".") +makeExample('webpack/ts/config/webpack.common.js', null, 'config/webpack.common.js')(format=".")
a#inside-webpack-commonjs
:marked :marked
### Inside _webpack.common.js_ ### Inside _webpack.common.js_
Webpack is a NodeJS-based tool that reads configuration from a JavaScript _commonjs_ module file. Webpack is a NodeJS-based tool that reads configuration from a JavaScript commonjs module file.
The configuration imports dependencies with `require` statements The configuration imports dependencies with `require` statements
and exports several objects as properties of a `module.exports` object. and exports several objects as properties of a `module.exports` object.
* [`entries`](#common-entries) - the entry-point files that define the bundles. * [`entry`](#common-entries)&mdash;the entry-point files that define the bundles.
* [`resolve`](#common-resolve) - how to resolve file names when they lack extensions. * [`resolve`](#common-resolve)&mdash;how to resolve file names when they lack extensions.
* [`module.rules`](#common-rules) - `module` is an object with `rules` for deciding how files are loaded. * [`module.rules`](#common-rules)&mdash; `module` is an object with `rules` for deciding how files are loaded.
* [`plugins`](#common-plugins) - creates instances of the plugins. * [`plugins`](#common-plugins)&mdash;creates instances of the plugins.
a#common-entries a#common-entries
:marked :marked
#### _entries_ #### _entry_
The first export is the *entries* object, described above: The first export is the `entry` object:
+makeExample('webpack/ts/config/webpack.common.js', 'entries', 'config/webpack.common.js')(format=".") +makeExample('webpack/ts/config/webpack.common.js', 'entries', 'config/webpack.common.js')(format=".")
:marked :marked
This *entries* object defines the three bundles: This `entry` object defines the three bundles:
* polyfills - the polyfills needed to run Angular applications in most modern browsers. * `polyfills`&mdash;the polyfills needed to run Angular applications in most modern browsers.
* vendor - the third-party dependencies such as Angular, lodash, and bootstrap.css. * `vendor`&mdash;the third-party dependencies such as Angular, lodash, and bootstrap.css.
* app - the application code. * `app`&mdash;the application code.
a#common-resolve a#common-resolve
:marked :marked
@ -302,23 +312,24 @@ a#common-rules
:marked :marked
:marked :marked
#### _module.rules_ #### _module.rules_
Rules tell Webpack which loaders to use for each file (AKA _module_): Rules tell Webpack which loaders to use for each file, or module:
+makeExample('webpack/ts/config/webpack.common.js', 'loaders', 'config/webpack.common.js')(format=".") +makeExample('webpack/ts/config/webpack.common.js', 'loaders', 'config/webpack.common.js')(format=".")
:marked :marked
* awesome-typescript-loader - a loader to transpile the Typescript code to ES5, guided by the `tsconfig.json` file * `awesome-typescript-loader`&mdash;a loader to transpile the Typescript code to ES5, guided by the `tsconfig.json` file.
* angular2-template-loader - loads angular components' template and styles * `angular2-template-loader`&mdash;loads angular components' template and styles.
* html - for component templates * `html-loader`&mdash;for component templates.
* images/fonts - Images and fonts are bundled as well. * images/fonts&mdash;Images and fonts are bundled as well.
* css - The pattern matches application-wide styles; the second handles component-scoped styles (the ones specified in a component's `styleUrls` metadata property) * CSS&mdash;the first pattern matches application-wide styles; the second handles
component-scoped styles (the ones specified in a component's `styleUrls` metadata property).
.l-sub-section .l-sub-section
:marked :marked
The first pattern is for the application-wide styles. It excludes `.css` files within the `src/app` directory The first pattern is for the application-wide styles. It excludes `.css` files within the `src/app` directory
where the component-scoped styles sit. The `ExtractTextPlugin` (described below) applies the `style` and `css` where the component-scoped styles sit. The `ExtractTextPlugin` (described below) applies the `style` and `css`
loaders to these files. loaders to these files.
The second pattern filters for component-scoped styles and loads them as strings via the `raw` loader &mdash; The second pattern filters for component-scoped styles and loads them as strings via the `raw-loader`,
which is what Angular expects to do with styles specified in a `styleUrls` metadata property. which is what Angular expects to do with styles specified in a `styleUrls` metadata property.
.l-sub-section .l-sub-section
@ -339,20 +350,20 @@ a(id="commons-chunk-plugin")
The `app.js` bundle should contain only application code. All vendor code belongs in the `vendor.js` bundle. The `app.js` bundle should contain only application code. All vendor code belongs in the `vendor.js` bundle.
Of course the application code `imports` vendor code. Of course the application code imports vendor code.
Webpack itself is not smart enough to keep the vendor code out of the `app.js` bundle. On its own, Webpack is not smart enough to keep the vendor code out of the `app.js` bundle.
The `CommonsChunkPlugin` does that job. The `CommonsChunkPlugin` does that job.
.l-sub-section .l-sub-section
:marked :marked
The `CommonsChunkPlugin` identifies the hierarchy among three _chunks_: `app` -> `vendor` -> `polyfills`. The `CommonsChunkPlugin` identifies the hierarchy among three _chunks_: `app` -> `vendor` -> `polyfills`.
Where Webpack finds that `app` has shared dependencies with `vendor`, it removes them from `app`. Where Webpack finds that `app` has shared dependencies with `vendor`, it removes them from `app`.
It would remove `polyfills` from `vendor` if they shared dependencies (which they don't). It would remove `polyfills` from `vendor` if they shared dependencies, which they don't.
a(id="html-webpack-plugin") a(id="html-webpack-plugin")
:marked :marked
#### *HtmlWebpackPlugin* #### _HtmlWebpackPlugin_
Webpack generates a number of js and css files. Webpack generates a number of js and CSS files.
You _could_ insert them into the `index.html` _manually_. That would be tedious and error-prone. You _could_ insert them into the `index.html` _manually_. That would be tedious and error-prone.
Webpack can inject those scripts and links for you with the `HtmlWebpackPlugin`. Webpack can inject those scripts and links for you with the `HtmlWebpackPlugin`.
@ -370,7 +381,7 @@ a(id="environment-configuration")
a(id="development-configuration") a(id="development-configuration")
.l-main-section .l-main-section
:marked :marked
### Development Configuration ### Development configuration
Here is the `webpack.dev.js` development configuration file. Here is the `webpack.dev.js` development configuration file.
@ -381,16 +392,17 @@ a(id="development-configuration")
Although you tell Webpack to put output bundles in the `dist` folder, Although you tell Webpack to put output bundles in the `dist` folder,
the dev server keeps all bundles in memory; it doesn't write them to disk. the dev server keeps all bundles in memory; it doesn't write them to disk.
You won't find any files in the `dist` folder (at least not any generated from *this development build*). You won't find any files in the `dist` folder, at least not any generated from *this development build*.
The `HtmlWebpackPlugin` (added in `webpack.common.js`) use the *publicPath* and the *filename* settings to generate The `HtmlWebpackPlugin`, added in `webpack.common.js`, uses the `publicPath` and the `filename` settings to generate
appropriate &lt;script&gt; and &lt;link&gt; tags into the `index.html`. appropriate `<script>` and `<link>` tags into the `index.html`.
The CSS styles are buried inside the Javascript bundles by default. The `ExtractTextPlugin` extracts them into The CSS styles are buried inside the Javascript bundles by default. The `ExtractTextPlugin` extracts them into
external `.css` files that the `HtmlWebpackPlugin` inscribes as &lt;link&gt; tags into the `index.html`. external `.css` files that the `HtmlWebpackPlugin` inscribes as `<link>` tags into the `index.html`.
Refer to the Webpack documentation for details on these and other configuration options in this file Refer to the [Webpack documentation](https://webpack.github.io/docs/) for details on these and
other configuration options in this file.
Grab the app code at the end of this guide and try: Grab the app code at the end of this guide and try:
@ -400,9 +412,9 @@ code-example(language="sh" class="code-shell").
a(id="production-configuration") a(id="production-configuration")
.l-main-section .l-main-section
:marked :marked
### Production Configuration ### Production configuration
Configuration of a *production* build resembles *development* configuration ... with a few key changes. Configuration of a *production* build resembles *development* configuration with a few key changes.
+makeExample('webpack/ts/config/webpack.prod.js', null, 'config/webpack.prod.js')(format=".") +makeExample('webpack/ts/config/webpack.prod.js', null, 'config/webpack.prod.js')(format=".")
@ -413,17 +425,17 @@ a(id="production-configuration")
Put the production output bundle files in the `dist` folder. Put the production output bundle files in the `dist` folder.
Webpack generates file names with cache-busting hash. Webpack generates file names with cache-busting hash.
Thanks to the `HtmlWebpackPlugin`, you don't have to update the `index.html` file when the hashes changes. Thanks to the `HtmlWebpackPlugin`, you don't have to update the `index.html` file when the hash changes.
There are additional plugins: There are additional plugins:
* **NoEmitOnErrorsPlugin** - stops the build if there is an error. * *`NoEmitOnErrorsPlugin`&mdash;stops the build if there is an error.
* **UglifyJsPlugin** - minifies the bundles. * *`UglifyJsPlugin`&mdash;minifies the bundles.
* **ExtractTextPlugin** - extracts embedded css as external files, adding cache-busting hash to the filename. * *`ExtractTextPlugin`&mdash;extracts embedded css as external files, adding cache-busting hash to the filename.
* **DefinePlugin** - use to define environment variables that you can reference within the application. * *`DefinePlugin`&mdash;use to define environment variables that you can reference within the application.
* **LoaderOptionsPlugins** - to override options of certain loaders. * *`LoaderOptionsPlugins`&mdash;to override options of certain loaders.
Thanks to the *DefinePlugin* and the `ENV` variable defined at top, you can enable Angular production mode like this: Thanks to the `DefinePlugin` and the `ENV` variable defined at top, you can enable Angular production mode like this:
+makeExample('webpack/ts/src/main.ts', 'enable-prod')(format=".") +makeExample('webpack/ts/src/main.ts', 'enable-prod')(format=".")
@ -436,7 +448,7 @@ code-example(language="sh" class="code-shell").
a(id="test-configuration") a(id="test-configuration")
.l-main-section .l-main-section
:marked :marked
### Test Configuration ### Test configuration
You don't need much configuration to run unit tests. You don't need much configuration to run unit tests.
You don't need the loaders and plugins that you declared for your development and production builds. You don't need the loaders and plugins that you declared for your development and production builds.
@ -449,7 +461,7 @@ a(id="test-configuration")
+makeExample('webpack/ts/config/webpack.test.js', null, 'config/webpack.test.js')(format=".") +makeExample('webpack/ts/config/webpack.test.js', null, 'config/webpack.test.js')(format=".")
:marked :marked
Reconfigure karma to use webpack to run the tests: Reconfigure [Karma](https://karma-runner.github.io/1.0/index.html) to use Webpack to run the tests:
+makeExample('webpack/ts/config/karma.conf.js', null, 'config/karma.conf.js')(format=".") +makeExample('webpack/ts/config/karma.conf.js', null, 'config/karma.conf.js')(format=".")
@ -465,7 +477,7 @@ a(id="test-configuration")
:marked :marked
Notice that you do _not_ load the application code explicitly. Notice that you do _not_ load the application code explicitly.
You tell Webpack to find and load the test files (the files ending in `.spec.ts`). You tell Webpack to find and load the test files (the files ending in `.spec.ts`).
Each spec file imports all &mdash; and only &mdash; the application source code that it tests. Each spec file imports all&mdash;and only&mdash;the application source code that it tests.
Webpack loads just _those_ specific application files and ignores the other files that you aren't testing. Webpack loads just _those_ specific application files and ignores the other files that you aren't testing.
:marked :marked
@ -510,7 +522,8 @@ code-example(language="sh" class="code-shell").
The <code>app.component.html</code> displays this downloadable Angular logo The <code>app.component.html</code> displays this downloadable Angular logo
<a href="https://raw.githubusercontent.com/angular/angular.io/master/public/resources/images/logos/angular2/angular.png" target="_blank"> <a href="https://raw.githubusercontent.com/angular/angular.io/master/public/resources/images/logos/angular2/angular.png" target="_blank">
<img src="/resources/images/logos/angular2/angular.png" height="40px" title="download Angular logo"></a>. <img src="/resources/images/logos/angular2/angular.png" height="40px" title="download Angular logo"></a>.
Create folder `images` under the project's "assets" folder, then right-click and download the image to that folder. Create a folder called `images` under the project's `assets` folder, then right-click (Cmd+click on Mac)
on the image and download it to that folder.
a#bundle-ts a#bundle-ts
:marked :marked
@ -524,9 +537,9 @@ a#bundle-ts
) )
<a id="highlights"></a> <a id="highlights"></a>
:marked :marked
### Highlights: ### Highlights
* There are no &lt;script&gt; or &lt;link&gt; tags in the `index.html`. * There are no `<script>` or `<link>` tags in the `index.html`.
The `HtmlWebpackPlugin` inserts them dynamically at runtime. The `HtmlWebpackPlugin` inserts them dynamically at runtime.
* The `AppComponent` in `app.component.ts` imports the application-wide css with a simple `import` statement. * The `AppComponent` in `app.component.ts` imports the application-wide css with a simple `import` statement.
@ -540,9 +553,9 @@ a#bundle-ts
The application imports these modules too; they'd be duplicated in the `app.js` bundle The application imports these modules too; they'd be duplicated in the `app.js` bundle
if the `CommonsChunkPlugin` hadn't detected the overlap and removed them from `app.js`. if the `CommonsChunkPlugin` hadn't detected the overlap and removed them from `app.js`.
<a id="conclusions"></a> <a id="conclusion"></a>
:marked :marked
## Conclusions ## Conclusion
You've learned just enough Webpack to configurate development, test and production builds You've learned just enough Webpack to configurate development, test and production builds
for a small Angular application. for a small Angular application.