docs: Remove outdated Webpack guide and example (#24478)
A supporting Webpack guide will be introduced as part of the guidance for ejecting from the Angular CLI. Closes #23937 PR Close #24478
This commit is contained in:
parent
aa66e84e44
commit
74f07f40e0
@ -1,12 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
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;
|
|
||||||
// #enddocregion
|
|
@ -1,17 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
Error.stackTraceLimit = Infinity;
|
|
||||||
|
|
||||||
require('core-js/es6');
|
|
||||||
require('core-js/es7/reflect');
|
|
||||||
|
|
||||||
require('zone.js/dist/zone');
|
|
||||||
require('zone.js/dist/zone-testing');
|
|
||||||
|
|
||||||
var appContext = require.context('../src', true, /\.spec\.ts/);
|
|
||||||
|
|
||||||
appContext.keys().forEach(appContext);
|
|
||||||
|
|
||||||
var testing = require('@angular/core/testing');
|
|
||||||
var browser = require('@angular/platform-browser-dynamic/testing');
|
|
||||||
|
|
||||||
testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting());
|
|
@ -1,39 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
var webpackConfig = require('./webpack.test');
|
|
||||||
|
|
||||||
module.exports = function (config) {
|
|
||||||
var _config = {
|
|
||||||
basePath: '',
|
|
||||||
|
|
||||||
frameworks: ['jasmine'],
|
|
||||||
|
|
||||||
files: [
|
|
||||||
{pattern: './config/karma-test-shim.js', watched: false}
|
|
||||||
],
|
|
||||||
|
|
||||||
preprocessors: {
|
|
||||||
'./config/karma-test-shim.js': ['webpack', 'sourcemap']
|
|
||||||
},
|
|
||||||
|
|
||||||
webpack: webpackConfig,
|
|
||||||
|
|
||||||
webpackMiddleware: {
|
|
||||||
stats: 'errors-only'
|
|
||||||
},
|
|
||||||
|
|
||||||
webpackServer: {
|
|
||||||
noInfo: true
|
|
||||||
},
|
|
||||||
|
|
||||||
reporters: ['progress', 'kjhtml'],
|
|
||||||
port: 9876,
|
|
||||||
colors: true,
|
|
||||||
logLevel: config.LOG_INFO,
|
|
||||||
autoWatch: false,
|
|
||||||
browsers: ['Chrome'],
|
|
||||||
singleRun: true
|
|
||||||
};
|
|
||||||
|
|
||||||
config.set(_config);
|
|
||||||
};
|
|
||||||
// #enddocregion
|
|
@ -1,81 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
var webpack = require('webpack');
|
|
||||||
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
||||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
|
||||||
var helpers = require('./helpers');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
// #docregion entries, one-entry, two-entries
|
|
||||||
entry: {
|
|
||||||
// #enddocregion one-entry, two-entries
|
|
||||||
'polyfills': './src/polyfills.ts',
|
|
||||||
// #docregion two-entries
|
|
||||||
'vendor': './src/vendor.ts',
|
|
||||||
// #docregion one-entry
|
|
||||||
'app': './src/main.ts'
|
|
||||||
},
|
|
||||||
// #enddocregion entries, one-entry, two-entries
|
|
||||||
|
|
||||||
// #docregion resolve
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.ts', '.js']
|
|
||||||
},
|
|
||||||
// #enddocregion resolve
|
|
||||||
|
|
||||||
// #docregion loaders
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.ts$/,
|
|
||||||
loaders: [
|
|
||||||
{
|
|
||||||
loader: 'awesome-typescript-loader',
|
|
||||||
options: { configFileName: helpers.root('src', 'tsconfig.json') }
|
|
||||||
} , 'angular2-template-loader'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.html$/,
|
|
||||||
loader: 'html-loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
|
|
||||||
loader: 'file-loader?name=assets/[name].[hash].[ext]'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
exclude: helpers.root('src', 'app'),
|
|
||||||
loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader?sourceMap' })
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
include: helpers.root('src', 'app'),
|
|
||||||
loader: 'raw-loader'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
// #enddocregion loaders
|
|
||||||
|
|
||||||
// #docregion plugins
|
|
||||||
plugins: [
|
|
||||||
// Workaround for angular/angular#11580
|
|
||||||
new webpack.ContextReplacementPlugin(
|
|
||||||
// The (\\|\/) piece accounts for path separators in *nix and Windows
|
|
||||||
/angular(\\|\/)core(\\|\/)@angular/,
|
|
||||||
helpers.root('./src'), // location of your src
|
|
||||||
{} // a map of your routes
|
|
||||||
),
|
|
||||||
|
|
||||||
new webpack.optimize.CommonsChunkPlugin({
|
|
||||||
name: ['app', 'vendor', 'polyfills']
|
|
||||||
}),
|
|
||||||
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
template: 'src/index.html'
|
|
||||||
})
|
|
||||||
]
|
|
||||||
// #enddocregion plugins
|
|
||||||
};
|
|
||||||
// #enddocregion
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
var webpackMerge = require('webpack-merge');
|
|
||||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
|
||||||
var commonConfig = require('./webpack.common.js');
|
|
||||||
var helpers = require('./helpers');
|
|
||||||
|
|
||||||
module.exports = webpackMerge(commonConfig, {
|
|
||||||
devtool: 'cheap-module-eval-source-map',
|
|
||||||
|
|
||||||
output: {
|
|
||||||
path: helpers.root('dist'),
|
|
||||||
publicPath: '/',
|
|
||||||
filename: '[name].js',
|
|
||||||
chunkFilename: '[id].chunk.js'
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
new ExtractTextPlugin('[name].css')
|
|
||||||
],
|
|
||||||
|
|
||||||
devServer: {
|
|
||||||
historyApiFallback: true,
|
|
||||||
stats: 'minimal'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #enddocregion
|
|
@ -1,41 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
var webpack = require('webpack');
|
|
||||||
var webpackMerge = require('webpack-merge');
|
|
||||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
|
||||||
var commonConfig = require('./webpack.common.js');
|
|
||||||
var helpers = require('./helpers');
|
|
||||||
|
|
||||||
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
|
|
||||||
|
|
||||||
module.exports = webpackMerge(commonConfig, {
|
|
||||||
devtool: 'source-map',
|
|
||||||
|
|
||||||
output: {
|
|
||||||
path: helpers.root('dist'),
|
|
||||||
publicPath: '/',
|
|
||||||
filename: '[name].[hash].js',
|
|
||||||
chunkFilename: '[id].[hash].chunk.js'
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
new webpack.NoEmitOnErrorsPlugin(),
|
|
||||||
new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618
|
|
||||||
mangle: {
|
|
||||||
keep_fnames: true
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
new ExtractTextPlugin('[name].[hash].css'),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': {
|
|
||||||
'ENV': JSON.stringify(ENV)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
new webpack.LoaderOptionsPlugin({
|
|
||||||
htmlLoader: {
|
|
||||||
minimize: false // workaround for ng2
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion
|
|
@ -1,55 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
var webpack = require('webpack');
|
|
||||||
var helpers = require('./helpers');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
devtool: 'inline-source-map',
|
|
||||||
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.ts', '.js']
|
|
||||||
},
|
|
||||||
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.ts$/,
|
|
||||||
loaders: [
|
|
||||||
{
|
|
||||||
loader: 'awesome-typescript-loader',
|
|
||||||
options: { configFileName: helpers.root('src', 'tsconfig.json') }
|
|
||||||
} , 'angular2-template-loader'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.html$/,
|
|
||||||
loader: 'html-loader'
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
|
|
||||||
loader: 'null-loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
exclude: helpers.root('src', 'app'),
|
|
||||||
loader: 'null-loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
include: helpers.root('src', 'app'),
|
|
||||||
loader: 'raw-loader'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
new webpack.ContextReplacementPlugin(
|
|
||||||
// The (\\|\/) piece accounts for path separators in *nix and Windows
|
|
||||||
/angular(\\|\/)core(\\|\/)@angular/,
|
|
||||||
helpers.root('./src'), // location of your src
|
|
||||||
{} // a map of your routes
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// #enddocregion
|
|
@ -1,21 +0,0 @@
|
|||||||
'use strict'; // necessary for es6 output in node
|
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
|
||||||
|
|
||||||
describe('QuickStart E2E Tests', function () {
|
|
||||||
|
|
||||||
let expectedMsg = 'Hello from Angular App with Webpack';
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should display: ${expectedMsg}`, function () {
|
|
||||||
expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display an image', function () {
|
|
||||||
expect(element(by.css('img')).isPresent()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"build": "build:webpack",
|
|
||||||
"run": "serve:cli",
|
|
||||||
"projectType": "systemjs"
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
module.exports = require('./config/karma.conf.js');
|
|
@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "angular2-webpack",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A webpack starter for Angular",
|
|
||||||
"scripts": {
|
|
||||||
"start": "webpack-dev-server --inline --progress --port 8080",
|
|
||||||
"test": "karma start",
|
|
||||||
"build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@angular/common": "~4.2.0",
|
|
||||||
"@angular/compiler": "~4.2.0",
|
|
||||||
"@angular/core": "~4.2.0",
|
|
||||||
"@angular/forms": "~4.2.0",
|
|
||||||
"@angular/http": "~4.2.0",
|
|
||||||
"@angular/platform-browser": "~4.2.0",
|
|
||||||
"@angular/platform-browser-dynamic": "~4.2.0",
|
|
||||||
"@angular/router": "~4.2.0",
|
|
||||||
"core-js": "^2.4.1",
|
|
||||||
"rxjs": "5.0.1",
|
|
||||||
"zone.js": "^0.8.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^6.0.45",
|
|
||||||
"@types/jasmine": "2.5.36",
|
|
||||||
"angular2-template-loader": "^0.6.0",
|
|
||||||
"awesome-typescript-loader": "^3.0.4",
|
|
||||||
"css-loader": "^0.26.1",
|
|
||||||
"extract-text-webpack-plugin": "2.0.0-beta.5",
|
|
||||||
"file-loader": "^0.9.0",
|
|
||||||
"html-loader": "^0.4.3",
|
|
||||||
"html-webpack-plugin": "^2.16.1",
|
|
||||||
"jasmine-core": "^2.4.1",
|
|
||||||
"karma": "^1.2.0",
|
|
||||||
"karma-chrome-launcher": "^2.0.0",
|
|
||||||
"karma-jasmine": "^1.0.2",
|
|
||||||
"karma-sourcemap-loader": "^0.3.7",
|
|
||||||
"karma-webpack": "^2.0.1",
|
|
||||||
"null-loader": "^0.1.1",
|
|
||||||
"raw-loader": "^0.5.1",
|
|
||||||
"rimraf": "^2.5.2",
|
|
||||||
"style-loader": "^0.13.1",
|
|
||||||
"typescript": "~2.3.1",
|
|
||||||
"webpack": "2.2.1",
|
|
||||||
"webpack-dev-server": "2.4.1",
|
|
||||||
"webpack-merge": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
/* #docregion */
|
|
||||||
main {
|
|
||||||
padding: 1em;
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 50px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
/* #enddocregion */
|
|
@ -1,7 +0,0 @@
|
|||||||
<!-- #docregion -->
|
|
||||||
<main>
|
|
||||||
<h1>Hello from Angular App with Webpack</h1>
|
|
||||||
|
|
||||||
<img src="../assets/images/angular.png">
|
|
||||||
</main>
|
|
||||||
<!-- #enddocregion -->
|
|
@ -1,16 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
describe('App', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({ declarations: [AppComponent]});
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('should work', () => {
|
|
||||||
let fixture = TestBed.createComponent(AppComponent);
|
|
||||||
expect(fixture.componentInstance instanceof AppComponent).toBe(true, 'should create AppComponent');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// #enddocregion
|
|
@ -1,16 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
// #docregion component
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
// #enddocregion component
|
|
||||||
import '../assets/css/styles.css';
|
|
||||||
|
|
||||||
// #docregion component
|
|
||||||
@Component({
|
|
||||||
selector: 'my-app',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: ['./app.component.css']
|
|
||||||
})
|
|
||||||
export class AppComponent { }
|
|
||||||
// #enddocregion
|
|
@ -1,16 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
BrowserModule
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
bootstrap: [ AppComponent ]
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
@ -1,6 +0,0 @@
|
|||||||
/* #docregion */
|
|
||||||
body {
|
|
||||||
background: #0147A7;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
/* #enddocregion */
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.3 KiB |
@ -1,14 +0,0 @@
|
|||||||
<!-- #docregion -->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<base href="/">
|
|
||||||
<title>Angular With Webpack</title>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<my-app>Loading...</my-app>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
<!-- #enddocregion -->
|
|
@ -1,14 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
import { enableProdMode } from '@angular/core';
|
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
|
||||||
|
|
||||||
// #docregion enable-prod
|
|
||||||
if (process.env.ENV === 'production') {
|
|
||||||
enableProdMode();
|
|
||||||
}
|
|
||||||
// #enddocregion enable-prod
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
||||||
// #enddocregion
|
|
@ -1,12 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import 'core-js/es6';
|
|
||||||
import 'core-js/es7/reflect';
|
|
||||||
require('zone.js/dist/zone');
|
|
||||||
|
|
||||||
if (process.env.ENV === 'production') {
|
|
||||||
// Production
|
|
||||||
} else {
|
|
||||||
// Development and test
|
|
||||||
Error['stackTraceLimit'] = Infinity;
|
|
||||||
require('zone.js/dist/long-stack-trace-zone');
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es5",
|
|
||||||
"module": "commonjs",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"sourceMap": true,
|
|
||||||
"emitDecoratorMetadata": true,
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"lib": ["es2015", "dom"],
|
|
||||||
"noImplicitAny": true,
|
|
||||||
"suppressImplicitAnyIndexErrors": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
// TODO(i): this no longer works. we need to review this example and if absolutely necessary rewrite it to use the
|
|
||||||
// rxjs-compat package
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
// Angular
|
|
||||||
import '@angular/platform-browser';
|
|
||||||
import '@angular/platform-browser-dynamic';
|
|
||||||
import '@angular/core';
|
|
||||||
import '@angular/common';
|
|
||||||
import '@angular/http';
|
|
||||||
import '@angular/router';
|
|
||||||
|
|
||||||
// RxJS
|
|
||||||
import 'rxjs';
|
|
||||||
|
|
||||||
// Other vendors for example jQuery, Lodash or Bootstrap
|
|
||||||
// You can import js, ts, css, sass, ...
|
|
||||||
// #enddocregion
|
|
@ -1,3 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
module.exports = require('./config/webpack.dev.js');
|
|
||||||
// #enddocregion
|
|
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"files":[
|
|
||||||
"!**/*.d.ts",
|
|
||||||
"!**/*.js",
|
|
||||||
"!**/*.[0-9].*",
|
|
||||||
"config/**/*",
|
|
||||||
"webpack.config.js",
|
|
||||||
"karma.webpack.conf.js"
|
|
||||||
],
|
|
||||||
"removeSystemJsConfig": true,
|
|
||||||
"type": "webpack"
|
|
||||||
}
|
|
@ -132,7 +132,7 @@ QuickStart identifies two *typings*, or `d.ts`, files:
|
|||||||
* [jasmine](http://jasmine.github.io/) typings for the Jasmine test framework.
|
* [jasmine](http://jasmine.github.io/) typings for the Jasmine test framework.
|
||||||
|
|
||||||
* [node](https://www.npmjs.com/package/@types/node) for code that references objects in the *Node.js®* environment;
|
* [node](https://www.npmjs.com/package/@types/node) for code that references objects in the *Node.js®* environment;
|
||||||
you can view an example in the [webpack](guide/webpack) page.
|
|
||||||
|
|
||||||
QuickStart doesn't require these typings but many of the samples do.
|
QuickStart doesn't require these typings but many of the samples do.
|
||||||
|
|
||||||
|
@ -1,801 +0,0 @@
|
|||||||
# Webpack: An Introduction
|
|
||||||
|
|
||||||
<style>
|
|
||||||
h4 {font-size: 17px !important; text-transform: none !important;}
|
|
||||||
.syntax { font-family: Consolas, 'Lucida Sans', Courier, sans-serif; color: black; font-size: 85%; }
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[**Webpack**](https://webpack.github.io/) 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 used elsewhere in the documentation.
|
|
||||||
This guide offers a taste of Webpack and explains how to use it with Angular applications.
|
|
||||||
|
|
||||||
|
|
||||||
{@a top}
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
|
|
||||||
# Contents
|
|
||||||
|
|
||||||
* [What is Webpack?](guide/webpack#what-is-webpack)
|
|
||||||
|
|
||||||
* [Entries and outputs](guide/webpack#entries-outputs)
|
|
||||||
* [Multiple bundles](guide/webpack#multiple-bundles)
|
|
||||||
* [Loaders](guide/webpack#loaders)
|
|
||||||
* [Plugins](guide/webpack#plugins)
|
|
||||||
|
|
||||||
* [Configuring Webpack](guide/webpack#configure-webpack)
|
|
||||||
|
|
||||||
* [Polyfills](guide/webpack#polyfills)
|
|
||||||
* [Common configuration](guide/webpack#common-configuration)
|
|
||||||
* [Inside `webpack.common.js`](guide/webpack#inside-webpack-commonjs)
|
|
||||||
|
|
||||||
* [entry](guide/webpack#common-entries)
|
|
||||||
* [resolve extension-less imports](guide/webpack#common-resolves)
|
|
||||||
* [`module.rules`](guide/webpack#common-rules)
|
|
||||||
* [Plugins](guide/webpack#plugins)
|
|
||||||
* [`CommonsChunkPlugin`](guide/webpack#commons-chunk-plugin)
|
|
||||||
* [`HtmlWebpackPlugin`](guide/webpack#html-webpack-plugin)
|
|
||||||
|
|
||||||
* [Environment specific configuration](guide/webpack#environment-configuration)
|
|
||||||
* [Development configuration](guide/webpack#development-configuration)
|
|
||||||
* [Production configuration](guide/webpack#production-configuration)
|
|
||||||
* [Test configuration](guide/webpack#test-configuration)
|
|
||||||
|
|
||||||
* [Trying it out](guide/webpack#try)
|
|
||||||
* [Highlights](guide/webpack#highlights)
|
|
||||||
* [Conclusion](guide/webpack#conclusion)
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
You can also <a href="generated/zips/webpack/webpack.zip" target="_blank">download the final result.</a>
|
|
||||||
|
|
||||||
{@a what-is-webpack}
|
|
||||||
|
|
||||||
## What is Webpack?
|
|
||||||
|
|
||||||
Webpack is a powerful module bundler.
|
|
||||||
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_.
|
|
||||||
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`.
|
|
||||||
|
|
||||||
|
|
||||||
{@a entries-outputs}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Entries and outputs
|
|
||||||
|
|
||||||
You supply Webpack with one or more *entry* files and let it find and incorporate the dependencies that radiate from those entries.
|
|
||||||
The one entry point file in this example is the application's root file, `src/main.ts`:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="one-entry" title="webpack.config.js (single entry)" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Webpack inspects that file and traverses its `import` dependencies recursively.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/src/app/app.component.ts" region="component" title="src/main.ts" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
<code-example name="webpack.config.js (single output)" language="javascript">
|
|
||||||
output: {
|
|
||||||
filename: 'app.js'
|
|
||||||
}
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
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}
|
|
||||||
|
|
||||||
|
|
||||||
#### 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.
|
|
||||||
|
|
||||||
Change the configuration so that it has two entry points, `main.ts` and `vendor.ts`:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="javascript">
|
|
||||||
entry: {
|
|
||||||
app: 'src/app.ts',
|
|
||||||
vendor: 'src/vendor.ts'
|
|
||||||
},
|
|
||||||
|
|
||||||
output: {
|
|
||||||
filename: '[name].js'
|
|
||||||
}
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
Webpack constructs two separate dependency graphs
|
|
||||||
and emits *two* bundle files, one called `app.js` containing only the application code and
|
|
||||||
another called `vendor.js` with all the vendor dependencies.
|
|
||||||
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The `[name]` in the output name is a *placeholder* that a Webpack plugin replaces with the entry names,
|
|
||||||
`app` and `vendor`. Plugins are [covered later](guide/webpack#commons-chunk-plugin) in the guide.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
To tell Webpack what belongs in the vendor bundle,
|
|
||||||
add a `vendor.ts` file that only imports the application's third-party modules:
|
|
||||||
|
|
||||||
<code-example path="webpack/src/vendor.ts" title="src/vendor.ts" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a loaders}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Loaders
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="javascript">
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.ts$/,
|
|
||||||
loader: 'awesome-typescript-loader'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
loaders: 'style-loader!css-loader'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
When Webpack encounters `import` statements like the following,
|
|
||||||
it applies the `test` RegEx patterns.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="typescript">
|
|
||||||
import { AppComponent } from './app.component.ts';
|
|
||||||
|
|
||||||
import 'uiframework/dist/uiframework.css';
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
Then it applies the `style` loader to append the css inside `<style>` elements on the page.
|
|
||||||
|
|
||||||
|
|
||||||
{@a plugins}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Plugins
|
|
||||||
|
|
||||||
Webpack has a build pipeline with well-defined phases.
|
|
||||||
Tap into that pipeline with plugins such as the `uglify` minification plugin:
|
|
||||||
|
|
||||||
<code-example language="javascript">
|
|
||||||
plugins: [
|
|
||||||
new webpack.optimize.UglifyJsPlugin()
|
|
||||||
]
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a 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.
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
mkdir angular-webpack
|
|
||||||
cd angular-webpack
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Add these files:
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
|
|
||||||
<code-pane title="package.json" path="webpack/package.webpack.json">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="src/tsconfig.json" path="webpack/src/tsconfig.1.json">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="webpack.config.js" path="webpack/webpack.config.js">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="karma.conf.js" path="webpack/karma.webpack.conf.js">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="config/helpers.js" path="webpack/config/helpers.js">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Many of these files should be familiar from other Angular documentation guides,
|
|
||||||
especially the [Typescript configuration](guide/typescript-configuration) and
|
|
||||||
[npm packages](guide/npm-packages) guides.
|
|
||||||
|
|
||||||
Webpack, the plugins, and the loaders are also installed as packages.
|
|
||||||
They are listed in the updated `packages.json`.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Open a terminal window and install the npm packages.
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
npm install
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a polyfills}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Polyfills
|
|
||||||
|
|
||||||
You'll need polyfills to run an Angular application in most browsers as explained
|
|
||||||
in the [Browser Support](guide/browser-support) guide.
|
|
||||||
|
|
||||||
Polyfills should be bundled separately from the application and vendor bundles.
|
|
||||||
Add a `polyfills.ts` like this one to the `src/` folder.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/src/polyfills.ts" title="src/polyfills.ts" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="callout is-critical">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header>
|
|
||||||
Loading polyfills
|
|
||||||
</header>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Load `zone.js` early within `polyfills.ts`, immediately after the other ES6 and metadata shims.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Because this bundle file will load first, `polyfills.ts` is also a good place to configure the browser environment
|
|
||||||
for production or development.
|
|
||||||
|
|
||||||
|
|
||||||
{@a common-configuration}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Common configuration
|
|
||||||
|
|
||||||
Developers typically have separate configurations for development, production, and test environments.
|
|
||||||
All three have a lot of configuration in common.
|
|
||||||
|
|
||||||
Gather the common configuration in a file called `webpack.common.js`.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" title="config/webpack.common.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a inside-webpack-commonjs}
|
|
||||||
|
|
||||||
|
|
||||||
### Inside _webpack.common.js_
|
|
||||||
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.
|
|
||||||
|
|
||||||
* [`entry`](guide/webpack#common-entries)—the entry-point files that define the bundles.
|
|
||||||
* [`resolve`](guide/webpack#common-resolves)—how to resolve file names when they lack extensions.
|
|
||||||
* [`module.rules`](guide/webpack#common-rules)— `module` is an object with `rules` for deciding how files are loaded.
|
|
||||||
* [`plugins`](guide/webpack#common-plugins)—creates instances of the plugins.
|
|
||||||
|
|
||||||
|
|
||||||
{@a common-entries}
|
|
||||||
|
|
||||||
|
|
||||||
#### _entry_
|
|
||||||
|
|
||||||
The first export is the `entry` object:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="entries" title="config/webpack.common.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
{@a common-resolves}
|
|
||||||
|
|
||||||
|
|
||||||
#### _resolve_ extension-less imports
|
|
||||||
|
|
||||||
The app will `import` dozens if not hundreds of JavaScript and TypeScript files.
|
|
||||||
You could write `import` statements with explicit extensions like this example:
|
|
||||||
|
|
||||||
<code-example language="typescript">
|
|
||||||
import { AppComponent } from './app.component.ts';
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
But most `import` statements don't mention the extension at all.
|
|
||||||
Tell Webpack to resolve extension-less file requests by looking for matching files with
|
|
||||||
`.ts` extension or `.js` extension (for regular JavaScript files and pre-compiled TypeScript files).
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="resolve" title="config/webpack.common.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
If Webpack should resolve extension-less files for styles and HTML,
|
|
||||||
add `.css` and `.html` to the list.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a common-rules}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### _module.rules_
|
|
||||||
Rules tell Webpack which loaders to use for each file, or module:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="loaders" title="config/webpack.common.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* `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-loader`—for component templates.
|
|
||||||
* images/fonts—Images and fonts are bundled as well.
|
|
||||||
* CSS—the first pattern matches application-wide styles; the second handles
|
|
||||||
component-scoped styles (the ones specified in a component's `styleUrls` metadata property).
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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`,
|
|
||||||
which is what Angular expects to do with styles specified in a `styleUrls` metadata property.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Multiple loaders can be chained using the array notation.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a common-plugins}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### _plugins_
|
|
||||||
Finally, create instances of three plugins:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.common.js" region="plugins" title="config/webpack.common.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a commons-chunk-plugin}
|
|
||||||
|
|
||||||
|
|
||||||
#### *CommonsChunkPlugin*
|
|
||||||
|
|
||||||
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.
|
|
||||||
On its own, Webpack is not smart enough to keep the vendor code out of the `app.js` bundle.
|
|
||||||
The `CommonsChunkPlugin` does that job.
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a html-webpack-plugin}
|
|
||||||
|
|
||||||
|
|
||||||
#### _HtmlWebpackPlugin_
|
|
||||||
|
|
||||||
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`.
|
|
||||||
|
|
||||||
|
|
||||||
{@a environment-configuration}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Environment-specific configuration
|
|
||||||
|
|
||||||
The `webpack.common.js` configuration file does most of the heavy lifting.
|
|
||||||
Create separate, environment-specific configuration files that build on `webpack.common`
|
|
||||||
by merging into it the peculiarities particular to the target environments.
|
|
||||||
|
|
||||||
These files tend to be short and simple.
|
|
||||||
|
|
||||||
|
|
||||||
{@a development-configuration}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Development configuration
|
|
||||||
|
|
||||||
Here is the `webpack.dev.js` development configuration file.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.dev.js" title="config/webpack.dev.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The development build relies on the Webpack development server, configured near the bottom of the file.
|
|
||||||
|
|
||||||
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*.
|
|
||||||
|
|
||||||
|
|
||||||
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 `<link>` tags into the `index.html`.
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
npm start
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a production-configuration}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Production configuration
|
|
||||||
|
|
||||||
Configuration of a *production* build resembles *development* configuration with a few key changes.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.prod.js" title="config/webpack.prod.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
You'll deploy the application and its dependencies to a real production server.
|
|
||||||
You won't deploy the artifacts needed only in development.
|
|
||||||
|
|
||||||
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 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.
|
|
||||||
|
|
||||||
Thanks to the `DefinePlugin` and the `ENV` variable defined at top, you can enable Angular production mode like this:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/src/main.ts" region="enable-prod" title="src/main.ts" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Grab the app code at the end of this guide and try:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a 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.
|
|
||||||
You probably don't need to load and process the application-wide styles files for unit tests and doing so would slow you down;
|
|
||||||
you'll use the `null` loader for those CSS files.
|
|
||||||
|
|
||||||
You could merge the test configuration into the `webpack.common` configuration and override the parts you don't want or need.
|
|
||||||
But it might be simpler to start over with a completely fresh configuration.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/webpack.test.js" title="config/webpack.test.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reconfigure [Karma](https://karma-runner.github.io/1.0/index.html) to use Webpack to run the tests:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/karma.conf.js" title="config/karma.conf.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
You don't precompile the TypeScript; Webpack transpiles the Typescript files on the fly, in memory, and feeds the emitted JS directly to Karma.
|
|
||||||
There are no temporary files on disk.
|
|
||||||
|
|
||||||
The `karma-test-shim` tells Karma what files to pre-load and
|
|
||||||
primes the Angular test framework with test versions of the providers that every app expects to be pre-loaded.
|
|
||||||
|
|
||||||
|
|
||||||
<code-example path="webpack/config/karma-test-shim.js" title="config/karma-test-shim.js" linenums="false">
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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—and only—the application source code that it tests.
|
|
||||||
Webpack loads just _those_ specific application files and ignores the other files that you aren't testing.
|
|
||||||
|
|
||||||
|
|
||||||
Grab the app code at the end of this guide and try:
|
|
||||||
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
|
||||||
npm test
|
|
||||||
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
{@a try}
|
|
||||||
|
|
||||||
## Trying it out
|
|
||||||
|
|
||||||
Here is the source code for a small application that bundles with the
|
|
||||||
Webpack techniques covered in this guide.
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
|
|
||||||
<code-pane title="src/index.html" path="webpack/src/index.html">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="src/main.ts" path="webpack/src/main.ts">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="src/assets/css/styles.css" path="webpack/src/assets/css/styles.css">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.ts" path="webpack/src/app/app.component.ts">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.html" path="webpack/src/app/app.component.html">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.css" path="webpack/src/app/app.component.css">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.component.spec.ts" path="webpack/src/app/app.component.spec.ts">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="src/app/app.module.ts" path="webpack/src/app/app.module.ts">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The <code>app.component.html</code> displays this downloadable Angular logo
|
|
||||||
<a href="assets/images/logos/angular/angular.png">
|
|
||||||
<img src="assets/images/logos/angular/angular.png" height="40px" title="download Angular logo"></a>.
|
|
||||||
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}
|
|
||||||
|
|
||||||
|
|
||||||
Here again are the TypeScript entry-point files that define the `polyfills` and `vendor` bundles.
|
|
||||||
|
|
||||||
<code-tabs>
|
|
||||||
|
|
||||||
<code-pane title="src/polyfills.ts" path="webpack/src/polyfills.ts">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
<code-pane title="src/vendor.ts" path="webpack/src/vendor.ts">
|
|
||||||
|
|
||||||
</code-pane>
|
|
||||||
|
|
||||||
</code-tabs>
|
|
||||||
|
|
||||||
{@a highlights}
|
|
||||||
|
|
||||||
<h3 class="no-toc">Highlights</h3>
|
|
||||||
|
|
||||||
* 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.
|
|
||||||
|
|
||||||
* The `AppComponent` itself has its own html template and css file. WebPack loads them with calls to `require()`.
|
|
||||||
Webpack stashes those component-scoped files in the `app.js` bundle too.
|
|
||||||
You don't see those calls in the source code;
|
|
||||||
they're added behind the scenes by the `angular2-template-loader` plug-in.
|
|
||||||
|
|
||||||
* The `vendor.ts` consists of vendor dependency `import` statements that drive the `vendor.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`.
|
|
||||||
{@a conclusion}
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
You've learned just enough Webpack to configurate development, test and production builds
|
|
||||||
for a small Angular application.
|
|
||||||
|
|
||||||
_You could always do more_. Search the web for expert advice and expand your Webpack knowledge.
|
|
||||||
|
|
||||||
[Back to top](guide/webpack#top)
|
|
@ -61,12 +61,6 @@
|
|||||||
"hidden": true
|
"hidden": true
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
"url": "guide/webpack",
|
|
||||||
"title": "Webpack: An Introduction",
|
|
||||||
"hidden": true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"url": "guide/quickstart",
|
"url": "guide/quickstart",
|
||||||
"title": "Getting Started",
|
"title": "Getting Started",
|
||||||
|
@ -25,7 +25,7 @@ The zipper will use this information for creating new zips.
|
|||||||
|
|
||||||
## Three kinds of examples
|
## Three kinds of examples
|
||||||
|
|
||||||
The majority of examples in AIO use `System.js` but there are also `CLI` and `Webpack` projects. This
|
The majority of examples in AIO use `CLI`, with some additionally using `Webpack` and upgrade usiing `SystemJS`. This
|
||||||
tool is able to differentiate between them.
|
tool is able to differentiate between them.
|
||||||
|
|
||||||
The boilerplate uses a `package.json` that contains packages and scripts to run any kind of example.
|
The boilerplate uses a `package.json` that contains packages and scripts to run any kind of example.
|
||||||
@ -44,7 +44,6 @@ Here you find a:
|
|||||||
|
|
||||||
* **base.json** - All the common scripts and packages
|
* **base.json** - All the common scripts and packages
|
||||||
* **cli.json** - Extra scripts and packages for the CLI
|
* **cli.json** - Extra scripts and packages for the CLI
|
||||||
* **webpack.json** - Extra scripts and packages for Webpack
|
|
||||||
* **universal.json** - Extra scripts and packages for universal
|
* **universal.json** - Extra scripts and packages for universal
|
||||||
* **i18n.json** - Extra scripts and packages for i18n
|
* **i18n.json** - Extra scripts and packages for i18n
|
||||||
* **systemjs.json** - All the System.js related packages but it also contains the remainder scripts
|
* **systemjs.json** - All the System.js related packages but it also contains the remainder scripts
|
||||||
@ -68,11 +67,11 @@ In both `stackblitz.json` and `zipper.json` you can use two extra properties for
|
|||||||
{
|
{
|
||||||
...
|
...
|
||||||
"removeSystemJsConfig": true,
|
"removeSystemJsConfig": true,
|
||||||
"type": "webpack"
|
"type": "testing"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This would generate a zip for a webpack application and it will also remove everything related with
|
This would generate a zip for a testing application and it will also remove everything related with
|
||||||
SystemJS.
|
SystemJS.
|
||||||
|
|
||||||
## Executing the zip generation
|
## Executing the zip generation
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"scripts": [
|
|
||||||
{ "name": "start:webpack", "rename": "start" },
|
|
||||||
{ "name": "test:webpack", "rename": "test" },
|
|
||||||
{ "name": "build:webpack", "rename": "build" }
|
|
||||||
],
|
|
||||||
"dependencies": [],
|
|
||||||
"devDependencies": [
|
|
||||||
"angular2-template-loader",
|
|
||||||
"awesome-typescript-loader",
|
|
||||||
"css-loader",
|
|
||||||
"extract-text-webpack-plugin",
|
|
||||||
"file-loader",
|
|
||||||
"html-loader",
|
|
||||||
"html-webpack-plugin",
|
|
||||||
"karma-sourcemap-loader",
|
|
||||||
"karma-webpack",
|
|
||||||
"null-loader",
|
|
||||||
"raw-loader",
|
|
||||||
"rimraf",
|
|
||||||
"style-loader",
|
|
||||||
"webpack",
|
|
||||||
"webpack-dev-server",
|
|
||||||
"webpack-merge"
|
|
||||||
]
|
|
||||||
}
|
|
@ -113,7 +113,6 @@ class ExampleZipper {
|
|||||||
'!**/package.json',
|
'!**/package.json',
|
||||||
'!**/example-config.json',
|
'!**/example-config.json',
|
||||||
'!**/wallaby.js',
|
'!**/wallaby.js',
|
||||||
'!**/package.webpack.json',
|
|
||||||
// AoT related files
|
// AoT related files
|
||||||
'!**/aot/**/*.*',
|
'!**/aot/**/*.*',
|
||||||
'!**/*-aot.*'
|
'!**/*-aot.*'
|
||||||
|
@ -18,7 +18,6 @@ const EXAMPLE_CONFIG_FILENAME = 'example-config.json';
|
|||||||
const IGNORED_EXAMPLES = [ // temporary ignores
|
const IGNORED_EXAMPLES = [ // temporary ignores
|
||||||
'quickstart',
|
'quickstart',
|
||||||
'setup',
|
'setup',
|
||||||
'webpack',
|
|
||||||
'upgrade-p'
|
'upgrade-p'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -26,13 +26,7 @@
|
|||||||
"serve:cli": "http-server dist/",
|
"serve:cli": "http-server dist/",
|
||||||
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
|
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
|
||||||
"serve:aot": "lite-server -c bs-config.aot.json",
|
"serve:aot": "lite-server -c bs-config.aot.json",
|
||||||
"start:webpack": "webpack-dev-server --inline --progress --port 8080",
|
|
||||||
"test:webpack": "karma start karma.webpack.conf.js",
|
|
||||||
"build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail",
|
|
||||||
"build:babel": "babel src -d src --extensions \".es6\" --source-maps",
|
"build:babel": "babel src -d src --extensions \".es6\" --source-maps",
|
||||||
"build:uni-client": "webpack --config webpack.config.client.js",
|
|
||||||
"build:uni": "webpack --config webpack.config.universal.js",
|
|
||||||
"serve:uni": "node dist/server.js",
|
|
||||||
|
|
||||||
"clean": "rimraf src/dist && rimraf src/app/*.js* && rimraf src/universal/*.js* && rimraf src/main.js*",
|
"clean": "rimraf src/dist && rimraf src/app/*.js* && rimraf src/universal/*.js* && rimraf src/main.js*",
|
||||||
"copy-dist-files": "node ./copy-dist-files.js",
|
"copy-dist-files": "node ./copy-dist-files.js",
|
||||||
|
@ -58,12 +58,6 @@
|
|||||||
"@types/node": "^6.0.45",
|
"@types/node": "^6.0.45",
|
||||||
"canonical-path": "0.0.2",
|
"canonical-path": "0.0.2",
|
||||||
"concurrently": "^3.0.0",
|
"concurrently": "^3.0.0",
|
||||||
"copy-webpack-plugin": "^4.0.1",
|
|
||||||
"css-loader": "^0.26.1",
|
|
||||||
"extract-text-webpack-plugin": "2.0.0-beta.5",
|
|
||||||
"file-loader": "^0.9.0",
|
|
||||||
"html-loader": "^0.4.3",
|
|
||||||
"html-webpack-plugin": "^2.16.1",
|
|
||||||
"http-server": "^0.9.0",
|
"http-server": "^0.9.0",
|
||||||
"jasmine-core": "~2.99.1",
|
"jasmine-core": "~2.99.1",
|
||||||
"jasmine-marbles": "^0.3.1",
|
"jasmine-marbles": "^0.3.1",
|
||||||
@ -74,7 +68,6 @@
|
|||||||
"karma-jasmine": "~1.1.1",
|
"karma-jasmine": "~1.1.1",
|
||||||
"karma-jasmine-html-reporter": "^0.2.2",
|
"karma-jasmine-html-reporter": "^0.2.2",
|
||||||
"karma-phantomjs-launcher": "^1.0.2",
|
"karma-phantomjs-launcher": "^1.0.2",
|
||||||
"karma-sourcemap-loader": "^0.3.7",
|
|
||||||
"lite-server": "^2.2.2",
|
"lite-server": "^2.2.2",
|
||||||
"lodash": "^4.16.2",
|
"lodash": "^4.16.2",
|
||||||
"phantomjs-prebuilt": "^2.1.7",
|
"phantomjs-prebuilt": "^2.1.7",
|
||||||
@ -85,7 +78,6 @@
|
|||||||
"rollup-plugin-node-resolve": "2.0.0",
|
"rollup-plugin-node-resolve": "2.0.0",
|
||||||
"rollup-plugin-uglify": "^1.0.1",
|
"rollup-plugin-uglify": "^1.0.1",
|
||||||
"source-map-explorer": "^1.3.2",
|
"source-map-explorer": "^1.3.2",
|
||||||
"ts-loader": "^4.2.0",
|
|
||||||
"ts-node": "^5.0.1",
|
"ts-node": "^5.0.1",
|
||||||
"tslint": "^5.9.1",
|
"tslint": "^5.9.1",
|
||||||
"typescript": "2.7.2",
|
"typescript": "2.7.2",
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user