神刀安全网

Angular2初探

  Angular2是Google下一代MV*框架,用于构建复杂浏览器应用。Angular2给WEB或移动Apps带来了一揽子解决方案,从模板渲染到数据绑定,从Http服务到表单处理等等,总之,你想要的,Angular2基本上都已封装好了。
  万事始于Hello World,不论Angular2怎么牛,咱们先得把官方的例子跑起来再说。这里使用基于webpack创建Angular应用。

环境准备
  node v5.x.x
  npm v3.x.x
step1:创建并配置本项目
创建项目目录:

mkdir angular2Demo cd angular2Demo

创建配置文件
典型的 Angular 项目需要一系列配置文件
package.json 用来标记出本项目所需的 npm 依赖包。
tsconfig.json 定义了 TypeScript 编译器如何从项目源文件生成 JavaScript 代码。
typings.json 为那些 TypeScript 编译器无法识别的库提供了额外的定义文件。
webpack.config.js为构建Angular应用所进行的一系列webpack配置。


package.json

{   "name": "angular2demo",   "version": "1.0.0",   "description": "Angular 2 demo.",   "main": "index.js",   "scripts": {     "start": "webpack-dev-server --inline --progress --port 8080",     "test": "karma start",     "build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail",     "postinstall": "typings install"   },   "dependencies": {     "@angular/common": "2.0.0",     "@angular/compiler": "2.0.0",     "@angular/core": "2.0.0",     "@angular/forms": "2.0.0",     "@angular/http": "2.0.0",     "@angular/platform-browser": "2.0.0",     "@angular/platform-browser-dynamic": "2.0.0",     "@angular/router": "3.0.0",     "core-js": "^2.4.1",     "rxjs": "5.0.0-beta.12",     "zone.js": "^0.6.23"   },   "devDependencies": {     "angular2-template-loader": "^0.4.0",     "awesome-typescript-loader": "^2.2.4",     "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": "^1.2.0",     "karma-jasmine": "^1.0.2",     "karma-phantomjs-launcher": "^1.0.2",     "karma-sourcemap-loader": "^0.3.7",     "karma-webpack": "^1.8.0",     "null-loader": "^0.1.1",     "phantomjs-prebuilt": "^2.1.7",     "raw-loader": "^0.5.1",     "rimraf": "^2.5.2",     "style-loader": "^0.13.1",     "typescript": "^2.0.2",     "typings": "^1.3.2",     "webpack": "^1.13.0",     "webpack-dev-server": "^1.14.1",     "webpack-merge": "^0.14.0"   },   "repository": {     "type": "git",     "url": "git+https://github.com/HalZhan/angular2Demo.git"   },   "author": "halzhan",   "license": "MIT",   "bugs": {     "url": "https://github.com/HalZhan/angular2Demo/issues"   },   "homepage": "https://github.com/HalZhan/angular2Demo#readme" }

tsconfig.json

{   "compilerOptions": {     "target": "es5",     "module": "commonjs",     "moduleResolution": "node",     "sourceMap": true,     "emitDecoratorMetadata": true,     "experimentalDecorators": true,     "removeComments": false,     "noImplicitAny": true,     "suppressImplicitAnyIndexErrors": true   } }

typings.json

{   "globalDependencies": {     "core-js": "registry:dt/core-js#0.0.0+20160725163759",     "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",     "node": "registry:dt/node#6.0.0+20160909174046"   } }

webpack.config.js

module.exports = require('./config/webpack.dev.js'); // 待补充

karma.conf.js

module.exports = require('./config/karma.conf.js'); // 待补充

下面我们继续完善配置文件。
公共配置
  我们可以为开发、产品和测试环境定义分别各自的配置文件。 但三者总会有一些公共配置。 于是我们把那些公共的配置收集到一个名叫 webpack.common.js 的独立文件中。


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', // 运行Angular时所需的一些标准js     'vendor': './src/vendor.ts', // Angular、Lodash、bootstrap.css......     'app': './src/main.ts' // 应用代码   },    resolve: {     extensions: ['', '.js', '.ts'] // 加载的文件类型(明确的扩展名、.js、.ts)   },    module: {     loaders: [       {         test: //.ts$/,         loaders: ['awesome-typescript-loader',                   'angular2-template-loader' // 用于加载 Angular 组件的模板和样式         ]       }, // ts - 将typescript代码转译成es5的加载器,由tsconfig.json文件指导       {         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'       } // 模式匹配组件局部样式 ( 在组件元数据的 styleUrls 属性中指定的那些 )      ]   },    plugins: [     new webpack.optimize.CommonsChunkPlugin({       name: ['app', 'vendor', 'polyfills']     }), // 提取公共代码      new HtmlWebpackPlugin({       template: 'src/index.html'     }) // 自动向目标.html文件注入script和link标签   ] };

config/helpers.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;

开发环境配置
config/webpack.dev.js

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: 'http://localhost:8080/',     filename: '[name].js',     chunkFilename: '[id].chunk.js'   },    plugins: [     new ExtractTextPlugin('[name].css')   ],    devServer: {     historyApiFallback: true,     stats: 'minimal'   } });

产品环境配置
config/webpack.prod.js

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'   },    htmlLoader: {     minimize: false // workaround for ng2   },    plugins: [     new webpack.NoErrorsPlugin(), //  如果出现任何错误,就终止构建     new webpack.optimize.DedupePlugin(), // 检测完全相同 ( 以及几乎完全相同 ) 的文件,并把它们从输出中移除     new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618                                           // 最小化 (minify) 生成的包       mangle: {         keep_fnames: true       }     }),     new ExtractTextPlugin('[name].[hash].css'), // 把内嵌的 css 抽取成外部文件,并为其文件名添加“缓存无效哈希”     new webpack.DefinePlugin({ // 用来定义环境变量,以便我们在自己的程序中引用它       'process.env': {         'ENV': JSON.stringify(ENV)       }     })   ] });

(可选)测试环境配置
config/webpack.test.js

var helpers = require('./helpers');  module.exports = {   devtool: 'inline-source-map',    resolve: {     extensions: ['', '.ts', '.js']   },    module: {     loaders: [       {         test: //.ts$/,         loaders: ['awesome-typescript-loader', 'angular2-template-loader']       },       {         test: //.html$/,         loader: 'html'        },       {         test: //.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,         loader: 'null'       },       {         test: //.css$/,         exclude: helpers.root('src', 'app'),         loader: 'null'       },       {         test: //.css$/,         include: helpers.root('src', 'app'),         loader: 'raw'       }     ]   } }

(可选)Karma单元测试配置
config/karma.conf.js

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'],     port: 9876,     colors: true,     logLevel: config.LOG_INFO,     autoWatch: false,     browsers: ['PhantomJS'],     singleRun: true   };    config.set(_config); };

config/karma-test-shim.js
  告诉 Karma 哪些文件需要预加载,首要的是:带有“测试版提供商”的 Angular 测试框架是每个应用都希望预加载的。

Error.stackTraceLimit = Infinity;  require('core-js/es6'); require('core-js/es7/reflect');  require('zone.js/dist/zone'); require('zone.js/dist/long-stack-trace-zone'); require('zone.js/dist/proxy'); require('zone.js/dist/sync-test'); require('zone.js/dist/jasmine-patch'); require('zone.js/dist/async-test'); require('zone.js/dist/fake-async-test');  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());

step2:编写源码
src/index.html

<!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>

src/main.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { enableProdMode } from '@angular/core'; import { AppModule } from './app/app.module'; if (process.env.ENV === 'production') {   enableProdMode(); } platformBrowserDynamic().bootstrapModule(AppModule);

public/css/styles.css

body {     background: #0147A7;     color: #fff; }

src/app/app.component.ts

import { Component } from '@angular/core'; import '../../public/css/styles.css'; @Component({   selector: 'my-app',   templateUrl: './app.component.html',   styleUrls: ['./app.component.css'] }) export class AppComponent { }

src/app/app.component.html
这里需要用到Angular Logo,下载后放入”public/images/”目录下。

<main>   <h1>Hello from Angular App with Webpack</h1>   <img src="../../public/images/angular.png"> </main>

src/app/app.component.css

main {   padding: 1em;   font-family: Arial, Helvetica, sans-serif;   text-align: center;   margin-top: 50px;   display: block; }

(用于单元测试,可选)src/app/app.component.spec.ts

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');   }); });

src/app/app.module.ts

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 { }

src/vendor.ts

// 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, ...

src/polyfills.ts

import 'core-js/es6'; import 'core-js/es7/reflect'; require('zone.js/dist/zone'); if (process.env.ENV === 'production') {   // Production } else {   // Development   Error['stackTraceLimit'] = Infinity;   require('zone.js/dist/long-stack-trace-zone'); }

step3:编译运行

  1. 在项目根目录下,执行
    webpack --progress --colors

    (–progress –colors是为了查看进度,可以不用加)

  2. 全局安装webpack-dev-server
    npm install -g webpack-dev-server --verbose

    (–verbose可以显示安装详细信息,可以不用加上)

  3. 启动webpack server
    webpack-dev-server --content-base dist/

    (设置静态文件访问路径)


step4:查看结果
访问localhost:8080,如果一切顺利,我们能够看到最终的结果:

Angular2初探
angular2-start.png

Bingo !


样例源码已托管至github,如有兴趣可自行clone

git clone https://github.com/HalZhan/angular2Demo.git

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Angular2初探

分享到:更多 ()

评论 抢沙发

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