未加星标

Angular Build with Webpack from Scratch

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二05 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏

Angular Build with Webpack from Scratch

Derived from photo by Yann Caradec / flickr.com, CC BY-SA

This tutorial walks through creating awebpack-based build for the Angular Tour of Heroes sample application . By the end, you will have a basic build and development server with automatic refresh and source maps.

The tutorial is divided into two parts. In this first part, you setup the project and create the Angular-specific build. In part two, you process the other files of the application and setup the development server.

More importantly, you will understand what each piece of the webpack configuration does. Why is it important? How does it relate to other pieces of the build? This understanding is critical when you inevitably want to modify or add new webpack functionality.

Migrate Tour of Heroes

First, create a new directory for your project. Before copying any of the Tour of Heroes code into your repository, create a folder named src in the root of your project. This folder will house the source code related to the browser-based Angular web application. In contrast, the project's root directory is the place for configuration files for the build and overall project. These specific directory names and locations aren't required but consider partitioning your project's source code according to the application's concerns, e.g. client versus configuration.

Tip:Clone the Angular Tour of Heroes sample application locally to copy files easily.

Create the src directory within your project and copy the entire app directory, index.html , and styles.css files from Angular Tour of Heroes into the newly created src directory. Then, copy the tsconfig.json and package.json files into the project's root directory.

Your application structure should look like this:

├── src
| ├── app
| | └── (...)
| ├── index.html
| └── styles.css
├── package.json
└── tsconfig.json

Now, make a couple modifications to the copied content. First, delete the src\app\main-aot.ts file. Ahead-of-Time (AOT) compilation is outside the scope of this tutorial and keeping this file causes a TypeScript compilation error.

Next, modify the packages in the package.json file. Since the entire build system is changing, replace the package list under devDependencies with this list:

"devDependencies": {
"@types/node": "^6.0.45",
"angular2-template-loader": "^0.6.0",
"awesome-typescript-loader": "^3.0.3",
"css-loader": "^0.26.1",
"extract-text-webpack-plugin": "^2.0.0-beta.5",
"html-loader": "^0.4.3",
"html-webpack-plugin": "^2.16.1",
"raw-loader": "^0.5.1",
"rimraf": "^2.5.2",
"style-loader": "^0.13.1",
"typescript": "~2.0.10",
"webpack": "2.2.0",
"webpack-dev-server": "2.2.0-rc.0",
"webpack-replace": "^1.0.0"
}

For now, don't worry about these packages as they are noted throughout the relevant sections of the tutorial.

Now that the list of packages is updated, run npm install from the terminal to install the required packages.

Finally, replace the existing npm scripts with a single script to invoke the webpack build:

"scripts": {
"build": "rimraf dist && webpack"
}

Note:If you attempt to run this script from a tasks.json file in Visual Studio Code, webpack might throw an error. To work around, run the npm script from the terminal instead.

This script calls the npm package utility rimraf to clear the contents of the dist directory and then calls webpack. The dist directory will be where webpack saves the build output.

Going forward, use the build script by invoking the command npm run build in the terminal to create the build. As you iterate your build configuration, use this command to verify the output.

TypeScript Build

In most cases, an Angular application consists of TypeScript files using ES2015 modules with HTML templates and styles defined either in line with components or in external files. The webpack build needs to understand how to process this structure and bundle it into a format the browser understands.

The Angular framework requires a couple polyfill scripts from core-js and zone.js . In Tour of Heroes , these scripts are included in the index.html file prior to loading the application. Being that the bundling process uses ES2015 import statements to create the bundle, move these script references to a new file called index.ts . Later, when processing the index.html file, the build will reference this new script. Place the index.ts file in the src directory with the rest of the Angular application and add this code:

// Polyfills
import 'core-js/es6';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';
// App
import './app/main.ts';

In addition to the polyfills, this file also imports the main.ts script to bootstrap the Angular application.

Now, it's time to create the webpack configuration. By default, webpack looks for a file at the root of the working directory named webpack.config.js . Go ahead and create this file and add the following contents:

const path = require('path');
const source = path.resolve(__dirname, 'src', 'index.ts');
const destination = path.resolve(__dirname, 'dist');
module.exports = {
entry: source,
output: {
filename: 'index.js',
path: destination
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [{ test: /\.ts$/, loaders: [ 'awesome-typescript-loader' ]}
]
}
};

At a high level, this file contains three variables: path , source , and destination . The path variable represents an imported npm module to assist in concatenating the required file and directory paths represented by source and destination .

The configuration also defines an object literal as the module's exports. The object literal is the webpack configuration and has the following properties: entry , output , resolve , and module . The entry property points to the file where webpack begins to construct the dependency tree, in this case, the index.ts file you created earlier. The output property defines the output file's name and path, in this case, dist\index.js .

The resolve property assists loading the TypeScript files. Because the import statements don't typically use a file extension, webpack uses the extensions defined in resolve.extensions to reconcile the imports. The compilation of the TypeScript files is ultimately handled by the awesome-typescript-loader . This loader is included in the project as an npm package defined in the package.json file.

The module.rules property is an array of objects that represent which tools load which files. In webpack, there is a concept of a loader. Loaders are an extension point which customize how code is processed by the webpack build. The defined loaders array is used only when an import matches the regular expression supplied in the test property.

The awesome-typescript-loader compiles TypeScript into javascript. The loader is used only for files that match the regular expression /\.ts$/ as defined in the test property.

With this configuration defined, test your build by typing npm run build in the terminal. Look at the newly created dist folder to see the result one single JavaScript file index.js . Examine the contents and you will start to get a sense of how webpack packages the application dependencies.

Angular Component HTML and CSS

Compiling TypeScript to JavaScript is the first step in an Angular build. Now, you must include the contents of any external templates and styles. Components define these resources in the @Component decorator:

@Component({
templateUrl: 'my-template.html',
styleUrls: [ 'my-styles.css' ]
})
export class MyComponent { }

The angular2-template-loader is listed under defDependencies in the package.json file. It extends webpack to load these external files and place the contents in line with the component. The resulting code looks something like this:

@Component({
template: '<h1>Hello World!</h1>',
styles: ['h1 { color: blue }']
})
export class MyComponent { }

The angular2-template-loader requires that webpack understands how to load HTML and CSS files. Therefore, add another rule to the rules list to test for .css and .html files and use the raw-loader package. The raw-loader is a simple loader that emits the contents of a file as a string.

This is how the new rules configuration looks with these changes:

rules: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader','angular2-template-loader'
]
},
{
test: /\.(css|html)$/,
loader: 'raw-loader'
},
]

Run the build again to test that the new configuration works. To verify that the HTML templates are included, perform a search in the emitted index.js file for a piece of code from one of the external templates such as {{hero.name}} .

The moduleId Problem

The Tour of Heroes application is designed to use SystemJS. Instead of combining the ES2015 modules into one bundle on the server, SystemJS dynamically loads all of the modules it needs when the application runs in the browser.

To assist the dynamic loading process, developers oftentimes configure the moduleId property like this:

@Component({
moduleId: module.id,
templateUrl: 'my-template.html',
styleUrls: [ 'my-styles.css' ]
})
export class MyComponent { }

The value passed by module.id is populated at runtime by SystemJS. Since SystemJS is not there anymore to populate the property, it is not defined and Angular doesn't like this. It throws the error 'moduleId should be a string in "AppComponent".

One way to get around this is to manually change all of the files by removing the moduleId definitions. After all, who needs all of this boilerplate code anyway? However, you may not always have access to this code. You may be using code authored by a third party which hasn't in lined the templates as part of a build. They have moduleId defined so that consumers can use SystemJS if they choose.

For this tutorial, instead of manually removing the moduleId settings, webpack will do it for you. Use the webpack-replace loader (another npm package) to search for the moduleId settings and remove them.

The webpack rules configuration now looks like this:

rules: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader','angular2-template-loader'
]
},
{
test: /\.ts$/,
loader: 'webpack-replace',
query: {search: 'moduleId: module.id,',replace: ''
}
},
{
test: /\.(css|html)$/,
loader: 'raw-loader'
}
]

Run your build again using npm run build and search in the output for moduleId: module the search should return no results.

Finally, the webpack.config.js file looks like this:

const path = require('path');
const source = path.resolve(__dirname, 'src', 'index.ts');
const destination = path.resolve(__dirname, 'dist');
module.exports = {
entry: source,
output: {
filename: 'index.js',
path: destination
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [{ test: /\.ts$/, loaders: [ 'awesome-typescript-loader', 'angular2-template-loader' ]}, { test: /\.ts$/, loader: 'webpack-replace', query: { search: 'moduleId: module.id,', replace: '' }},{ test: /\.(css|html)$/, loader: 'raw-loader'}
]
}
};

The working directory structure now looks like this:

├── dist
├── node_modules
├── src
| ├── app
| | └── (...)
| ├── index.html
| ├── index.ts
| └── styles.css
├── package.json
├── tsconfig.json
└── webpack.config.js That's All for Now

This tutorial has taken you through the basics of building the Angular portion of the application. However, there are more pieces of the application that require processing. In part two, you will handle the index.html and CSS portions of the application. In addition, you will learn how to configure the webpack development server to run the application. Stay tuned.

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

分页:12
转载请注明
本文标题:Angular Build with Webpack from Scratch
本站链接:http://www.codesec.net/view/533960.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(32)