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
1 changed files with 191 additions and 178 deletions

View File

@ -14,24 +14,30 @@ style.
This guide offers a taste of Webpack and explains how to use it with Angular applications.
<a id="top"></a>
## Table of contents
[What is Webpack?](#what-is-webpack)
# Contents
* [What is Webpack?](#what-is-webpack)
* [Entries and outputs](#entries-outputs)
* [Multiple bundles](#multiple-bundles)
* [Loaders](#loaders)
* [Plugins](#plugins)
[Configuring Webpack](#configure-webpack)
* [Configuring Webpack](#configure-webpack)
* [Polyfills](#polyfills)
* [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)
* [Production configuration](#production-configuration)
* [Test configuration](#test-configuration)
[Trying it out](#try)
[Conclusions](#conclusions)
* [Trying it out](#try)
* [Highlights](#highlights)
* [Conclusion](#conclusion)
You can also <a href="/resources/zips/webpack/webpack.zip">download the final result.</a>
@ -41,12 +47,12 @@ style.
## What is Webpack?
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.
A bundle can include JavaScript, CSS styles, HTML, and almost any other kind of file.
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.
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=".")
:marked
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 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.
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.
You'll load it later with a `<script>` tag in the `index.html`.
a#multiple-bundles
:marked
#### Multiple bundles
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.
@ -120,7 +128,7 @@ a(id="loaders")
:marked
### 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.
Teach it to transform non-JavaScript file into their JavaScript equivalents with *loaders*.
Configure loaders for TypeScript and CSS as follows.
@ -139,7 +147,8 @@ a(id="loaders")
]
: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(language="typescript").
@ -148,15 +157,15 @@ a(id="loaders")
import 'uiframework/dist/uiframework.css';
: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 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.
Webpack applies chained loaders *right to left* so it applies
the `css` loader first (to flatten CSS `@import` and `url(...)` statements) and
then the `style` loader (to append the css inside *&lt;style&gt;* elements on the page).
Webpack applies chained loaders *right to left*. So it applies
the `css` loader first to flatten CSS `@import` and `url(...)` statements.
Then it applies the `style` loader to append the css inside `<style>` elements on the page.
a(id="plugins")
.l-main-section
@ -175,13 +184,13 @@ a(id="plugins")
a(id="configure-webpack")
.l-main-section
:marked
## Configure Webpack
## Configuring Webpack
After that brief orientation, you are ready to build your own Webpack configuration for Angular apps.
Begin by setting up the development environment.
Create a **new project folder**
Create a new project folder.
code-example(language="sh" class="code-shell").
mkdir angular-webpack
cd angular-webpack
@ -205,14 +214,14 @@ code-example(language="sh" class="code-shell").
.l-sub-section
:marked
Many of these files should be familiar from other Angular documentation guides,
especially the [_Typescript configuration_](../guide/typescript-configuration.html) and
[_npm packages_](../guide/npm-packages.html) guides.
especially the [Typescript configuration](../guide/typescript-configuration.html) and
[npm packages](../guide/npm-packages.html) guides.
Webpack, the plugins, and the loaders are also installed as packages.
They are listed in the updated `packages.json`.
: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").
npm install
@ -222,7 +231,7 @@ a#polyfills
### Polyfills
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.
Add a `polyfills.ts` like this one to the `src/` folder.
@ -241,7 +250,7 @@ a#polyfills
a(id="common-configuration")
.l-main-section
:marked
### Common Configuration
### Common configuration
Developers typically have separate configurations for development, production, and test environments.
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=".")
a#inside-webpack-commonjs
:marked
### 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
and exports several objects as properties of a `module.exports` object.
* [`entries`](#common-entries) - the entry-point files that define the bundles.
* [`resolve`](#common-resolve) - 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.
* [`plugins`](#common-plugins) - creates instances of the plugins.
* [`entry`](#common-entries)&mdash;the entry-point files that define the bundles.
* [`resolve`](#common-resolve)&mdash;how to resolve file names when they lack extensions.
* [`module.rules`](#common-rules)&mdash; `module` is an object with `rules` for deciding how files are loaded.
* [`plugins`](#common-plugins)&mdash;creates instances of the plugins.
a#common-entries
: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=".")
: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.
* vendor - the third-party dependencies such as Angular, lodash, and bootstrap.css.
* app - the application code.
* `polyfills`&mdash;the polyfills needed to run Angular applications in most modern browsers.
* `vendor`&mdash;the third-party dependencies such as Angular, lodash, and bootstrap.css.
* `app`&mdash;the application code.
a#common-resolve
:marked
@ -302,23 +312,24 @@ a#common-rules
:marked
:marked
#### _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=".")
:marked
* awesome-typescript-loader - a loader to transpile the Typescript code to ES5, guided by the `tsconfig.json` file
* angular2-template-loader - loads angular components' template and styles
* html - for component templates
* images/fonts - 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)
* `awesome-typescript-loader`&mdash;a loader to transpile the Typescript code to ES5, guided by the `tsconfig.json` file.
* `angular2-template-loader`&mdash;loads angular components' template and styles.
* `html-loader`&mdash;for component templates.
* images/fonts&mdash;Images and fonts are bundled as well.
* 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
:marked
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`
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.
.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.
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.
Of course the application code imports vendor code.
On its own, Webpack is not smart enough to keep the vendor code out of the `app.js` bundle.
The `CommonsChunkPlugin` does that job.
.l-sub-section
:marked
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`.
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")
: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.
Webpack can inject those scripts and links for you with the `HtmlWebpackPlugin`.
@ -370,7 +381,7 @@ a(id="environment-configuration")
a(id="development-configuration")
.l-main-section
:marked
### Development Configuration
### Development configuration
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,
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
appropriate &lt;script&gt; and &lt;link&gt; tags into the `index.html`.
The `HtmlWebpackPlugin`, added in `webpack.common.js`, uses the `publicPath` and the `filename` settings to generate
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
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:
@ -400,9 +412,9 @@ code-example(language="sh" class="code-shell").
a(id="production-configuration")
.l-main-section
: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=".")
@ -413,17 +425,17 @@ a(id="production-configuration")
Put the production output bundle files in the `dist` folder.
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:
* **NoEmitOnErrorsPlugin** - stops the build if there is an error.
* **UglifyJsPlugin** - minifies the bundles.
* **ExtractTextPlugin** - 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.
* **LoaderOptionsPlugins** - to override options of certain loaders.
* *`NoEmitOnErrorsPlugin`&mdash;stops the build if there is an error.
* *`UglifyJsPlugin`&mdash;minifies the bundles.
* *`ExtractTextPlugin`&mdash;extracts embedded css as external files, adding cache-busting hash to the filename.
* *`DefinePlugin`&mdash;use to define environment variables that you can reference within the application.
* *`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=".")
@ -436,7 +448,7 @@ code-example(language="sh" class="code-shell").
a(id="test-configuration")
.l-main-section
:marked
### Test Configuration
### Test configuration
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.
@ -449,7 +461,7 @@ a(id="test-configuration")
+makeExample('webpack/ts/config/webpack.test.js', null, 'config/webpack.test.js')(format=".")
: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=".")
@ -465,7 +477,7 @@ a(id="test-configuration")
:marked
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`).
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.
:marked
@ -510,7 +522,8 @@ code-example(language="sh" class="code-shell").
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">
<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
:marked
@ -524,9 +537,9 @@ a#bundle-ts
)
<a id="highlights"></a>
: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 `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
if the `CommonsChunkPlugin` hadn't detected the overlap and removed them from `app.js`.
<a id="conclusions"></a>
<a id="conclusion"></a>
:marked
## Conclusions
## Conclusion
You've learned just enough Webpack to configurate development, test and production builds
for a small Angular application.