神刀安全网

Angular 2 introduction to webpack

Webpack is a popular module bundler, a tool for bundling application source code in convenient chunks and for loading that code from a server into a browser.

It’s an excellent alternative to the SystemJS approach we use throughout the documentation. In this guide we get a taste of Webpack and how to use it with Angular 2 applications.

Table of contents

  • Development configuration
  • Production configuration

What is Webpack?

Webpack is a powerful module bundler. A bundle is a JavaScript file that incorporate 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 . With plugin "loaders" Webpack can preprocess and minify different non-JavaScript files such as TypeScript, SASS, and LESS files.

We determine what Webpack does and how it does it with a JavaScript configuration file, webpack.config.js .

Entries and outputs

We feed Webpack with one or more entry files and let it find and incorporate the dependencies that radiate from those entries. In this example, we start from the application’s root file, src/app.ts :

webpack.config.js (single entry)

entry: { app: ‘src/app.ts’ }

Webpack inspects that file and traverses its import dependencies recursively.

src/app.ts

import { Component } from ‘@angular/core’; @Component({ … }) export class AppComponent {}

Here it sees that we’re importing @angular/core so it adds that to its dependency list for (potential) inclusion in the bundle. It opens @angular/core and follows its network of import statements until it has build the complete dependency graph from app.ts down.

Then it outputs these files to the app.js bundle file designated in configuration:

webpack.config.js (single output)

output: { filename: ‘app.js’ }

This app.js output bundle is a single JavaScript file that contains our application source and its dependencies. We’ll load it later with a <script> tag in our index.html.

Multiple bundles

We probably do not want one giant bundle of everything. We’ll likely prefer to separate our volatile application app code from comparatively stable vendor code modules.

We change the configuration so that we have two entry points, app.ts and vendor.ts :

webpack.config.js (two entries)

entry: { app: ‘src/app.ts’, vendor: ‘src/vendor.ts’ }, output: { filename: ‘[name].js’ }

Webpack constructs two separate dependency graphs and emits two bundle files, one called app.js containing only our application code and another called vendor.js with all the vendor dependencies.

The [name] in the output name is a Webpack placeholder that is replaced with the entry names. app and vendor respectively.

We need a plugin to make this work; we’llin the chapter.

We met app.ts earlier. We wrote vendor.ts such that it imports the vendor modules we need:

src/vendor.ts

// Angular 2 import ‘@angular/platform-browser’; import ‘@angular/platform-browser-dynamic’; import ‘@angular/core’; import ‘@angular/common’; import ‘@angular/http’; import ‘@angular/router-deprecated’; // RxJS import ‘rxjs’; // Other vendors for example jQuery, Lodash or Bootstrap // You can import js, ts, css, sass, …

Loaders

Webpack can bundle any kind of file: JavaScript, TypeScript, CSS, SASS, LESS, images, html, fonts, whatever. Webpack itself doesn’t know what to do with a non-JavaScript file. We teach it to process such files into JavaScript with loaders . Here we configure loaders for TypeScript and CSS:

webpack.config.js (two entries)

loaders: [ { test: //.ts$/ loaders: ‘ts’ }, { test: //.css$/ loaders: ‘style!css’ } ]

As Webpack encounters import statements like these …

import { AppComponent } from ‘./app.component.ts’; import ‘uiframework/dist/uiframework.css’;

… it applies the test RegEx patterns. 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 ts (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 we 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 <style> elements on the page).

Plugins

Webpack has a build pipeline with well-defined phases. We tap into that pipeline with plugins such as the uglify minification plugin:

plugins: [ new webpack.optimize.UglifyJsPlugin() ]

Configure Webpack

After that brief orientation, we are ready to build our own Webpack configuration for Angular 2 apps.

Begin by setting up the development environment.

Create a new project folder

mkdir angular2-webpack cd angular2-webpack

Add these files to the root directory:

{ "name": "angular2-webpack", "version": "1.0.0", "description": "A webpack starter for angular 2", "scripts": { "start": "webpack-dev-server –inline –progress –port 8080", "test": "karma start", "build": "rm -rf dist && webpack –config config/webpack.prod.js –progress –profile –bail", "postinstall": "typings install" }, "license": "MIT", "dependencies": { "@angular/common": "2.0.0-rc.1", "@angular/compiler": "2.0.0-rc.1", "@angular/core": "2.0.0-rc.1", "@angular/http": "2.0.0-rc.1", "@angular/platform-browser": "2.0.0-rc.1", "@angular/platform-browser-dynamic": "2.0.0-rc.1", "@angular/router-deprecated": "2.0.0-rc.1", "es6-shim": "^0.35.0", "reflect-metadata": "0.1.2", "rxjs": "5.0.0-beta.6", "zone.js": "0.6.12" }, "devDependencies": { "css-loader": "^0.23.1", "extract-text-webpack-plugin": "^1.0.1", "file-loader": "^0.8.5", "html-loader": "^0.4.3", "html-webpack-plugin": "^2.15.0", "jasmine-core": "^2.4.1", "karma": "^0.13.22", "karma-jasmine": "^0.3.8", "karma-phantomjs-launcher": "^1.0.0", "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^1.7.0", "null-loader": "^0.1.1", "phantomjs-prebuilt": "^2.1.7", "raw-loader": "^0.5.1", "style-loader": "^0.13.1", "ts-loader": "^0.8.1", "typescript": "^1.8.9", "typings": "^0.7.12", "webpack": "^1.12.14", "webpack-dev-server": "^1.14.1", "webpack-merge": "^0.9.0" } } { "ambientDependencies": { "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", "jasmine": "registry:dt/jasmine#2.2.0+20160412134438", "node": "registry:dt/node#4.0.0+20160509154515" } } { "compilerOptions": { "target": "es5", "module": "commonjs", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "removeComments": false, "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true }, "exclude": [ "node_modules", "typings/main", "typings/main.d.ts" ] } module.exports = require(‘./config/webpack.dev.js’); module.exports = require(‘./config/karma.conf.js’); var path = require(‘path’); var _root = path.resolve(__dirname, ‘..’); function root(args) { args = Array.prototype.slice.call(arguments, 0); return path.join.apply(path, [_root].concat(args)); } exports.root = root;

Many of these files and much of their content should be familiar from other Angular 2 documentation chapters.

Learn about the package.json in thenpm packages chapter. We require packages for Webpack use in addition to the ones listed in that chapter.

Learn about tsconfig.json and typings.json in the Typescript configuration chapter.

Open a terminal/console window and install the npm packages with npm install .

Common Configuration

We will define separate configurations for development, production, and test environments. All three have some configuration in common. We’ll gather that common configuration in a separate file called webpack.common.js .

Let’s see the entire file and then walk through it a section at a time:

config/webpack.common.js

var webpack = require(‘webpack’); var HtmlWebpackPlugin = require(‘html-webpack-plugin’); var ExtractTextPlugin = require(‘extract-text-webpack-plugin’); var helpers = require(‘./helpers’); module.exports = { entry: { ‘polyfills’: ‘./src/polyfills.ts’, ‘vendor’: ‘./src/vendor.ts’, ‘app’: ‘./src/main.ts’ }, resolve: { extensions: [”, ‘.js’, ‘.ts’] }, module: { loaders: [ { test: //.ts$/, loader: ‘ts’ }, { test: //.html$/, loader: ‘html’ }, { test: //.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, loader: ‘file?name=assets/[name].[hash].[ext]’ }, { test: //.css$/, exclude: helpers.root(‘src’, ‘app’), loader: ExtractTextPlugin.extract(‘style’, ‘css?sourceMap’) }, { test: //.css$/, include: helpers.root(‘src’, ‘app’), loader: ‘raw’ } ] }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: [‘app’, ‘vendor’, ‘polyfills’] }), new HtmlWebpackPlugin({ template: ‘src/index.html’ }) ] };

Webpack is a NodeJS-based tool so its configuration is a JavaScript commonjs module file that begins with require statements as such files do.

The configuration exports several objects, beginning with the entries described earlier:

config/webpack.common.js

entry: { ‘polyfills’: ‘./src/polyfills.ts’, ‘vendor’: ‘./src/vendor.ts’, ‘app’: ‘./src/main.ts’ },

We are splitting our application into three bundles:

  • polyfills – the standard polyfills we require to run Angular 2 applications in most modern browsers.
  • vendor – the vendor files we need: Angular 2, lodash, bootstrap.css…
  • app – our application code.
Loading polyfills

Load Zone.js early, immediately after the other ES6 and metadata shims.

Our app will import dozens if not hundreds of JavaScript and TypeScript files. We might write import statements with explicit extensions as in this example:

import { AppComponent } from ‘./app.component.ts’;

But most of our import statements won’t mention the extension at all. So we tell Webpack to resolve module file requests by looking for matching files with

  • an explicit extention (signified by the empty extension string, '' ) or
  • .js extension (for regular JavaScript files and pre-compiled TypeScript files) or
  • .ts extension.

config/webpack.common.js

resolve: { extensions: [”, ‘.js’, ‘.ts’] },

We could add .css and .html later if we want Webpack to resolve extension-less files with those extension too.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Angular 2 introduction to webpack

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址