Angular之路--帶你來搭建Webpack 2 + Angular 4項目

上個月Angular發佈了4.0.0版本,少年們,趕快學起來吧,這篇文章帶領你們搭建一個簡單的Angular應用,會盡可能詳細的把每一個點都解釋到。javascript

首先我選擇了用webpack2來做爲打包工具,選擇wenpack2的理由不言而喻。這裏假設你已經瞭解webpack2的一些原理,下面開始來學習吧~css

詳細代碼能夠看個人git項目html

1、配置 webpack

首先新建一個項目文件夾java

mkdir angular-dream
cd angular-dream複製代碼

在控制檯中輸入命令 npm init ,建立 package.json 文件。如圖:node

建立package.json文件

在控制檯中能夠一路回車。固然,這裏我命名了項目的名稱爲 angular-dream ,還有一些其餘的信息。

建立好以後用編輯器(我使用的是webstorm)打開這個項目。webpack

package.json 文件的配置

關於 package.json 文件裏面的一些參數的含義,能夠參考阮一峯老師寫的這篇文章git

{
  "name": "angular2-dream",
  "version": "1.0.0",
  "description": "Hello Angular2",
  "scripts": {
    "start": "webpack-dev-server --config config/webpack.dev.js --progress",
    "test": "karma start",
    "build": "webpack --config config/webpack.dev.js --progress --profile --bail",
    "webpack": "webpack",
    "rimraf": "rimraf"
  },
  "keywords": [
    "angular2",
    "webpack"
  ],
  "author": "yanmeng@hujiang.com",
  "license": "MIT",
  "dependencies": {
    "@angular/animations": "~4.0.1",
    "@angular/common": "~4.0.0",
    "@angular/compiler": "~4.0.0",
    "@angular/core": "^4.0.1",
    "@angular/forms": "~4.0.1",
    "@angular/http": "~4.0.1",
    "core-js": "^2.4.1",
    "rxjs": "5.2.0",
    "zone.js": "^0.8.5"
  },
  "devDependencies": {
    "reflect-metadata": "^0.1.10",
    "html-webpack-plugin": "^2.28.0",
    "@angular/compiler-cli": "~4.0.1",
    "@angular/platform-browser": "~4.0.1",
    "@angular/platform-browser-dynamic": "~4.0.1",
    "@angular/platform-server": "~4.0.1",
    "@angular/router": "~4.0.1",
    "@angularclass/hmr": "^1.2.2",
    "@angularclass/hmr-loader": "^3.0.2",
    "@types/jasmine": "^2.5.43",
    "@types/node": "^6.0.45",
    "angular2-template-loader": "^0.6.0",
    "awesome-typescript-loader": "^3.0.4",
    "bootstrap": "^4.0.0-alpha.6",
    "bootstrap-sass": "^3.3.7",
    "css-loader": "^0.26.1",
    "extract-text-webpack-plugin": "2.0.0-beta.5",
    "file-loader": "^0.9.0",
    "font-awesome": "^4.7.0",
    "html-loader": "^0.4.3",
    "postcss-loader": "^1.3.1",
    "raw-loader": "^0.5.1",
    "style-loader": "^0.13.1",
    "to-string-loader": "^1.1.5",
    "ts-helpers": "^1.1.2",
    "url-loader": "^0.5.7",
    "webpack": "2.2.0",
    "webpack-dev-server": "2.2.0-rc.0",
    "webpack-merge": "^2.4.0",
    "typescript": "^2.2.2"
  }
}複製代碼
  • @angular/compiler - Angular的模板編譯器。 它會理解模板,而且把模板轉化成代碼,以供應用程序運行和渲染。 開發人員一般不會直接跟這個編譯器打交道,而是經過platform-browser-dynamic或離線模板編譯器間接使用它。
  • @angular/platform-browser - 與DOM和瀏覽器相關的每樣東西,特別是幫助往DOM中渲染的那部分。 這個包還包含bootstrapStatic方法,用來引導那些在產品構建時須要離線預編譯模板的應用程序
  • @angular/platform-browser-dynamic - 爲應用程序提供一些提供商和bootstrap方法,以便在客戶端編譯模板。不要用於離線編譯。 咱們使用這個包在開發期間引導應用,以及引導plunker中的範例。
  • core-js - 爲全局上下文(window)打的補丁,提供了ES2015(ES6)的不少基礎特性。 咱們也能夠把它換成提供了相同內核API的其它填充庫。 一旦全部的「主流瀏覽器」都實現了這些API,這個依賴就能夠去掉了。
  • reflect-metadata - 一個由Angular和TypeScript編譯器共享的依賴包。

tsconfig.json 文件的配置

在項目的根目錄下建立 tsconfig.json 文件。程序員

瀏覽器不能直接執行 TypeScript ,須要用編譯器轉譯成JavaScript,並且編譯器須要進行一些配置。 tsconfig.json 的配置就是指導編譯器如何生成JavaScript文件。es6

{
  "compilerOptions": {
    "declaration": false,
    "module": "commonjs", // 組織代碼的方式
    "target": "es5", // 編譯目標平臺
    "moduleResolution": "node",
    "sourceMap": true, // 把ts文件變異成js文件時,是否生成對應的SourceMap文件
    "emitDecoratorMetadata": true, // 讓TypeScript支持爲帶有裝飾器的聲明生成元數據
    "experimentalDecorators": true, // 是否啓用實驗性裝飾器特性
    "noImplicitAny": true,
    "lib": ["dom", "es6"],
    "suppressImplicitAnyIndexErrors": true
  },
  "exclude": [
    "node_modules",
    "dist"
  ],
  "awesomeTypescriptLoaderOptions": {
    "forkChecker": true,
    "useWebpackText": true
  },
  "compileOnSave": false,
  "buildOnSave": false
}複製代碼

noImplicitAny 標誌是 true 而且TypeScript編譯器沒法推斷出類型時,它仍然會生成JavaScript文件。 可是它也會報告一個錯誤。 不少飽經滄桑的程序員更喜歡這種嚴格的設置,由於類型檢查能在編譯期間捕獲更多意外錯誤。github

建立 webpack.config.js文件

在根目錄下建立 webpack.config.js文件

module.exports = require('./config/webpack.dev.js');複製代碼

如今在控制檯中執行 npm install 命令,安裝項目的依賴。

2、Polyfills

配置好上述的幾個文件以後呢,咱們在項目中的根目錄下建立一個 src 文件夾。

src 文件夾的下面新建一個 polyfills.ts 文件。

polyfills.ts 文件裏引入了運行Angular應用時所需的一些標準js。

import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/set';
import 'core-js/es6/weak-map';
import 'core-js/es6/weak-set';
import 'core-js/es6/typed';

/** Evergreen browsers require these. **/
import 'core-js/es6/reflect';

import 'core-js/es7/reflect';

/*************************************************************************************************** * Zone JS is required by Angular itself. */
import 'zone.js/dist/zone';

import 'ts-helpers';

if (process.env.ENV === 'production') {
  // Production
} else {
  // Development and test
  Error['stackTraceLimit'] = Infinity;
  require('zone.js/dist/long-stack-trace-zone');
}複製代碼

3、Vendor

src 文件夾的下面新建一個 vendor.ts 文件。

vendor.ts 文件裏面引入了一些第三方的依賴。

// Angular
//包含全部提供商依賴
import '@angular/platform-browser';
import '@angular/platform-browser-dynamic';
import '@angular/compiler';
import '@angular/core';  // 存放核心代碼,如變化監測機制,依賴注入機制,渲染,裝飾器等。
import '@angular/common';
import '@angular/http';
import '@angular/router';

// RxJS
import 'rxjs/Observable';
import 'rxjs/Subscription';
import 'rxjs/Subject';
import 'rxjs/BehaviorSubject';

// Bootsctrap
import 'bootstrap/dist/css/bootstrap.css';
import 'font-awesome/css/font-awesome.css';複製代碼

4、Main

src 文件夾的下面新建一個 main.ts 文件。

main.ts 文件中,咱們指定了項目的根模塊爲 AppModule

import {AppModule} from './app/app.module';
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

platformBrowserDynamic().bootstrapModule(AppModule);

// platformBrowserDynamic().bootstrapModule()方法來編譯啓用AppModule模塊
// 根據當前的運行環境,如操做系統、瀏覽器,來初始化一個運行環境,而後從這個環境裏面運行AppModule。複製代碼

5、config

在根目錄下建立一個 config 文件夾

helpers.js

config 文件夾下面建立一個 helpers.js 文件。

在這裏請注意入口 polyfills,vendorapp 的前後順序。

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;複製代碼

webpack.common.js

config 文件夾下面建立一個 webpack.common.js 文件。

const helpers = require('./helpers');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    'polyfills': './src/polyfills.ts', // 運行Angular時所需的一些標準js
    'vendor': './src/vendor.ts', // Angular、Lodash、bootstrap.css......
    'app': './src/main.ts' // 應用代碼
  },
  resolve: { // 解析模塊路徑時的配置
    extensions: ['.ts', '.js'] // 制定模塊的後綴,在引入模塊時就會自動補全
  },
  module: {
    rules: [ // 告訴webpack每一類文件須要使用什麼加載器來處理
      {
        test   : /\.ts$/,
        loaders: ['awesome-typescript-loader', 'angular2-template-loader']
        //awesome-typescript-loader - 一個用於把TypeScript代碼轉譯成ES5的加載器,它會由tsconfig.json文件提供指導
        //angular2-template-loader - 用於加載Angular組件的模板和樣式
      }, {
        test: /\.json$/,
        use : 'json-loader'
      }, {
        test: /\.styl$/,
        loader: 'css-loader!stylus-loader'
      }, {
        test   : /\.css$/,
        loaders: ['to-string-loader', 'css-loader']
      }, {
        test: /\.html$/,
        use: 'raw-loader',
        exclude: [helpers.root('src/index.html')]
        //html - 爲組件模板準備的加載器
      }, {
        test:/\.(jpg|png|gif)$/,
        use:"file-loader"
      }, {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        use : "url-loader?limit=10000&minetype=application/font-woff"
      }, {
        test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        use : "file-loader"
      }
    ]
  },
  plugins: [
    //熱替換
    new webpack.HotModuleReplacementPlugin(),
    new webpack.optimize.CommonsChunkPlugin({
      name: ['vendor', 'polyfills']
      //多個html共用一個js文件,提取公共代碼
    }),

    new HtmlWebpackPlugin({
      template: './src/index.html'
      // 自動向目標.html文件注入script和link標籤
    })
  ]
};複製代碼

webpack.dev.js

config 文件夾下面建立一個 webpack.dev.js 文件。

var webpackMerge = require('webpack-merge');
var commonConfig = require('./webpack.common.js');
const helpers = require('./helpers');

module.exports = webpackMerge(commonConfig, {
  output   : {
    path      : helpers.root('dist'),
    publicPath: '/',
    filename  : '[name].js'
  },
  devServer: {
    port              : 8080,
    historyApiFallback: true
  }
});複製代碼

至此,如今的目錄結構就以下圖所示:


由於咱們尚未建立 AppModule ,因此 main.ts 文件會被標紅。

6、根模塊 AppModule

基本的配置已經完成啦,如今咱們來建立根模塊~

src 文件下面新建一個 app 文件夾,

建立 app.component.ts

app 文件夾下面新建 app.component.ts 文件

import { Component } from "@angular/core";

@Component({
  selector   : 'root-app',
  templateUrl: './app.component.html'
})
export class AppComponent {
  constructor() {}
}複製代碼

建立 app.component.html

app 文件夾下面新建 app.component.html 文件

<h1 class="title">Hello Angular2</h1>

<router-outlet></router-outlet>複製代碼

建立 app.routes.ts

這裏咱們用一下路由來完成頁面之間的跳轉

import { Routes } from '@angular/router';
import { AppComponent } from "./app.component";
export const routes: Routes = [ // Routes類型的數組
  {
    path      : 'index',
    component : AppComponent
  },{
    path      : '',
    redirectTo: 'index',
    pathMatch : 'full'
  }
];複製代碼

建立 app.module.ts

app 文件夾下面新建 app.module.ts 文件

import { AppComponent } from './app.component';
import { routes } from './app.routes';
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { RouterModule } from "@angular/router";
import { NgModule } from "@angular/core";
//@NgModule裝飾器用來爲模塊定義元數據
@NgModule({ // @NgModule 用來定義模塊用的裝飾器
  declarations: [AppComponent], // 導入模塊所依賴的組件、指令等,用於指定這個模塊的視圖類
  imports: [
    BrowserModule, //包含了commonModule和applicationModule模塊,封裝在瀏覽器平臺運行時的一些工具庫
    FormsModule,  // 表單相關的組件指令等,包含了[(ngModel)]
    RouterModule.forRoot(routes,{useHash: false}), // RouterModule.forRoot()方法來建立根路由模塊
  ], // 導入當前模塊所須要的其餘模塊
  bootstrap: [AppComponent], // 標記出引導組件
  //把這個AppComponent標記爲引導 (bootstrap) 組件。當Angular引導應用時,它會在DOM中渲
  //染AppComponent,並把結果放進index.html的元素內部。
})
export class AppModule { }複製代碼

6、宿主頁面

src 文件夾下面新建 index.html 文件

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Angular2 Hello Word</title>
    <base href="/">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <root-app>Loading...</root-app>
</body>
</html>複製代碼

好啦,此時的項目目錄結構就是下圖所示:

接下來運行 npm start 開始你的 Angular 之旅吧~

參考:

相關文章
相關標籤/搜索