Angular2 + Webpack项目搭建Demo
本文将从头开始编写实际的代码来完成一个angular2的demo。
题外话是其实angular2官网的快速开始项目已经很酷炫了,但其侧重快速二字,只够拿来练习玩耍,倒是github上确实已经有了一些不错的angular2-starter。
1. 安装必要的node环境与npm

当然TS环境也是必须的,目前TS已经更新到了2.1.5+,笔者使用的就是2.1.5版本,且最好使用2.0以上版本的TS,否则会有一些尴尬的问题(包括类型定义以及编译错误)。
2.关于编辑器
笔者使用的是VSCode,使用其他热门的编辑器都可以自己喜欢就行,甚至可以用VisualStudio(但是在网上见过有人用VS2015来开发涉及到npm包的项目,即使是Mac顶配版也能卡爆炸)。
3. 底层目录结构
想象自己在写一个后台语言项目,我们所写的文件最终都要经过编译生成目标文件才运行,ng2也是这样,编写的是.ts文件,最终由我们配置好的编译器(webpack)进行编译生成目标代码并运行。
所以除了angular2依赖以外,必须配置好底层的webpack。所有的依赖包都通过前面安装的npm来安装。下面给出package.json:
{
"name": "angular2-demo-yitim",
"version": "1.0.0",
"description": "angular2 demo by yitim",
"keywords": [
"angular2",
"webpack",
"typescript"
],
"author": "yitim <635928008@qq.com>",
"license": "MIT",
"scripts": {
"build:aot:prod": "npm run clean:dist && npm run clean:aot && webpack --config config/webpack.prod.js --progress --profile --bail",
"build:aot": "npm run build:aot:prod",
"build:dev": "npm run clean:dist && webpack --config config/webpack.dev.js --progress --profile",
"build:docker": "npm run build:prod && docker build -t angular2-webpack-start:latest .",
"build:prod": "npm run clean:dist && webpack --config config/webpack.prod.js --progress --profile --bail",
"build": "npm run build:dev",
"clean:dll": "npm run rimraf -- dll",
"clean:aot": "npm run rimraf -- compiled",
"clean:dist": "npm run rimraf -- dist",
"clean:install": "npm set progress=false && npm install",
"clean": "npm cache clean && npm run rimraf -- node_modules doc coverage dist compiled dll",
"docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./src/",
"lint": "npm run tslint \"src/**/*.ts\"",
"server:dev:hmr": "npm run server:dev -- --inline --hot",
"server:dev": "webpack-dev-server --config config/webpack.dev.js --open --progress --profile --watch --content-base src/",
"server:prod": "http-server dist -c-1 --cors",
"server": "npm run server:dev",
"start": "npm run server:dev",
"tslint": "tslint",
"version": "npm run build",
"watch:dev:hmr": "npm run watch:dev -- --hot",
"watch:dev": "npm run build:dev -- --watch",
"watch:prod": "npm run build:prod -- --watch",
"watch": "npm run watch:dev",
"webdriver-manager": "webdriver-manager",
"webdriver:start": "npm run webdriver-manager start",
"webdriver:update": "webdriver-manager update",
"webpack-dev-server": "webpack-dev-server",
"webpack": "webpack"
},
"dependencies": {
"@angular/common": "2.4.6",
"@angular/compiler": "2.4.6",
"@angular/core": "2.4.6",
"@angular/forms": "2.4.6",
"@angular/http": "2.4.6",
"@angular/platform-browser": "2.4.6",
"@angular/platform-browser-dynamic": "2.4.6",
"@angular/platform-server": "2.4.6",
"@angular/router": "3.4.6",
"@angularclass/conventions-loader": "^1.0.2",
"@angularclass/hmr": "~1.2.2",
"@angularclass/hmr-loader": "~3.0.2",
"core-js": "^2.4.1",
"crypto-browserify": "^3.11.0",
"crypto-js": "^3.1.9-1",
"http-server": "^0.9.0",
"ie-shim": "^0.1.0",
"reflect-metadata": "^0.1.9",
"rxjs": "5.0.2",
"zone.js": "0.7.6"
},
"devDependencies": {
"@angular/compiler-cli": "2.4.6",
"@types/hammerjs": "^2.0.33",
"@types/node": "^7.0.0",
"@types/selenium-webdriver": "~2.53.39",
"@types/source-map": "^0.5.0",
"@types/uglify-js": "^2.0.27",
"@types/webpack": "^2.0.0",
"add-asset-html-webpack-plugin": "^1.0.2",
"angular2-template-loader": "^0.6.0",
"assets-webpack-plugin": "^3.5.1",
"awesome-typescript-loader": "~3.0.0-beta.18",
"codelyzer": "~2.0.0-beta.4",
"copy-webpack-plugin": "^4.0.0",
"css-loader": "^0.26.0",
"exports-loader": "^0.6.3",
"expose-loader": "^0.7.1",
"extract-text-webpack-plugin": "~2.0.0-rc.2",
"file-loader": "^0.10.0",
"find-root": "^1.0.0",
"gh-pages": "^0.12.0",
"html-webpack-plugin": "^2.28.0",
"imports-loader": "^0.7.0",
"istanbul-instrumenter-loader": "1.2.0",
"json-loader": "^0.5.4",
"ng-router-loader": "^2.1.0",
"ngc-webpack": "1.1.0",
"npm-run-all": "^4.0.1",
"optimize-js-plugin": "0.0.4",
"parse5": "^3.0.1",
"protractor": "^4.0.14",
"raw-loader": "0.5.1",
"rimraf": "~2.5.4",
"sass-loader": "^4.1.1",
"script-ext-html-webpack-plugin": "^1.5.0",
"source-map-loader": "^0.1.5",
"string-replace-loader": "1.0.5",
"style-loader": "^0.13.1",
"to-string-loader": "^1.1.4",
"ts-node": "^2.0.0",
"tslib": "^1.5.0",
"tslint": "~4.4.2",
"tslint-loader": "^3.3.0",
"typedoc": "^0.5.3",
"typescript": "~2.1.5",
"url-loader": "^0.5.7",
"webpack": "2.2.0",
"webpack-dev-middleware": "^1.10.0",
"webpack-dev-server": "2.2.1",
"webpack-dll-bundles-plugin": "^1.0.0-beta.5",
"webpack-merge": "~2.6.1"
}
}
package.json
package.json用于管理npm依赖,然后还需要tsconfig.json来配置TS,以及tsconfig.webpack.json来配合webpack编译:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"noEmit": true,
"noEmitHelpers": true,
"importHelpers": true,
"strictNullChecks": false,
"lib": [
"dom",
"es6"
],
"typeRoots": [
"node_modules/@types",
"./typings/**/*.d.ts",
"../vendor/tslib/tslib.d.ts"
],
"types": [
"hammerjs",
"node",
"source-map",
"uglify-js",
"webpack"
]
},
"exclude": [
"node_modules",
"dist"
],
"awesomeTypescriptLoaderOptions": {
"forkChecker": true,
"useWebpackText": true
},
"compileOnSave": false,
"buildOnSave": false,
"atom": {
"rewriteTsconfig": false
}
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"noEmit": true,
"noEmitHelpers": true,
"importHelpers": true,
"strictNullChecks": false,
"lib": [
"es2015",
"dom"
],
"typeRoots": [
"node_modules/@types"
],
"types": [
"hammerjs",
"node"
]
},
"exclude": [
"node_modules",
"dist",
"src/**/*.spec.ts",
"src/**/*.e2e.ts"
],
"awesomeTypescriptLoaderOptions": {
"forkChecker": true,
"useWebpackText": true
},
"angularCompilerOptions": {
"genDir": "./compiled",
"skipMetadataEmit": true
},
"compileOnSave": false,
"buildOnSave": false,
"atom": {
"rewriteTsconfig": false
}
}
tsconfig.webpack.json
然后是webpack的配置文件,入口为webpack.config.js:
// Look in ./config folder for webpack.dev.js
switch (process.env.NODE_ENV) {
case 'prod':
case 'production':
module.exports = require('./config/webpack.prod')({env: 'production'});
break;
case 'dev':
case 'development':
default:
module.exports = require('./config/webpack.dev')({env: 'development'});
}
webpack.config.js
此配置文件将根据运行编译时的参数决定使用开发环境的编译方式还是生产环境的编译方式,具体的编译配置就不贴上来了,可以到文末给出的github地址查看整个项目。
4. angular2的配置
第3节的配置是项目npm依赖、TypeScript以及webpack的配置,给整个项目提供了依赖,并帮助编译以后会写的实际项目代码,与angular2的关系其实不大,但是是angular2项目运行的前提。现在要来配置angular2了,以webpack作为模块化工具的话,需要一个入口文件index.html以及几个入口脚本:
/*
* Angular bootstraping
*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { decorateModuleRef } from './app/environment';
import { bootloader } from '@angularclass/hmr';
/*
* App Module
* our top level module that holds all of our components
*/
import { AppModule } from './app'; /*
* Bootstrap our Angular app with a top level NgModule
*/
export function main(): Promise<any> {
return platformBrowserDynamic()
.bootstrapModule(AppModule)
.then(decorateModuleRef)
.catch((err) => console.error(err));
} // needed for hmr
// in prod this is replace for document ready
bootloader(main);
main.browser.ts
// TODO(gdi2290): switch to DLLs // Polyfills // import 'ie-shim'; // Internet Explorer 9 support // import 'core-js/es6';
// Added parts of es6 which are necessary for your project or your browser support requirements.
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';
import 'core-js/es6/reflect';
// see issue https://github.com/AngularClass/angular2-webpack-starter/issues/709
// import 'core-js/es6/promise'; import 'core-js/es7/reflect';
import 'zone.js/dist/zone'; if ('production' === ENV) {
// Production } else { // Development
Error.stackTraceLimit = Infinity; /* tslint:disable no-var-requires */
require('zone.js/dist/long-stack-trace-zone'); }
polyfills.browser.ts
前者的作用是引导angular2程序的运行,后者的作用是管理angular2的所有依赖(由于angular2使用了很多ES新特性,所以需要一些依赖来扩展不支持新特性的浏览器的功能)。
实际代码可能还需要有aot模式的引导文件(预编译模式,更适用于生产环境,效率高非常多),以及一个自定义的类型声明文件(帮助编写TS代码)。
5. 实际要写的代码——app目录与assets目录
配置好所有东西后,就轮到亲手来写angular2代码了,专门新建一个app目录来存放这些代码,以及一个assets文件来存放静态资源。
一个最简单的angular2项目需要以下几个文件:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ENV_PROVIDERS } from './environment';
@NgModule({
bootstrap: [ AppComponent ],
declarations: [ AppComponent],
imports: [
BrowserModule
],
providers: [ ENV_PROVIDERS ]
})
export class AppModule { }
app.module.ts
import {
Component, OnInit, ViewEncapsulation
} from '@angular/core';
@Component({
selector: 'my-app',
template: `<h1>Hello World!</h1>`,
})
export class AppComponent implements OnInit {
public ngOnInit() {
console.log('load app.component');
}
}
app.component.ts
一个是根模块一个是根组件,在此先不提angular2具体语法,先把项目成功运行起来为重。
为了让webpack找到我们的angular2代码,以及成功引导angular2项目,还必须添加一个环境文件以及一个索引文件:
// App
export * from './app.module';
index.ts
// Angular 2
import {
enableDebugTools,
disableDebugTools
} from '@angular/platform-browser';
import {
ApplicationRef,
enableProdMode
} from '@angular/core';
// Environment Providers
let PROVIDERS: any[] = [
// common env directives
]; // Angular debug tools in the dev console
// https://github.com/angular/angular/blob/86405345b781a9dc2438c0fbe3e9409245647019/TOOLS_JS.md
let _decorateModuleRef = <T>(value: T): T => { return value; }; if ('production' === ENV) {
enableProdMode(); // Production
_decorateModuleRef = (modRef: any) => {
disableDebugTools(); return modRef;
}; PROVIDERS = [
...PROVIDERS,
// custom providers in production
]; } else { _decorateModuleRef = (modRef: any) => {
const appRef = modRef.injector.get(ApplicationRef);
const cmpRef = appRef.components[0]; let _ng = (<any> window).ng;
enableDebugTools(cmpRef);
(<any> window).ng.probe = _ng.probe;
(<any> window).ng.coreTokens = _ng.coreTokens;
return modRef;
}; // Development
PROVIDERS = [
...PROVIDERS,
// custom providers in development
]; } export const decorateModuleRef = _decorateModuleRef; export const ENV_PROVIDERS = [
...PROVIDERS
];
environment.ts
下面是现在的文件目录结构:

现在只要先运行 npm install 安装好所有npm包,然后运行指令 npm run server:dev 就可以运行起第一个angular2项目了!

后记:
此angular2 demo的配置有使用到AngularClass的hmr插件,并且搭建的目的以学习与总结为主,实际开发中还需要配置单元测试等东西,可以直接查看AngularClass的angular-webpack-starter开源项目,其给出了一套非常完善的angular2启动项目,值得花费一些时间来看懂。
最后给出此demo的github地址:
https://github.com/yitimo/angular2-demo-yitim
Angular2 + Webpack项目搭建Demo的更多相关文章
- angular2+webpack的搭建过程遇到的问题记录
最近在由于公司的项目要重构,Superiors要求将原先的Ionic1+angular1+gulp用全新的Ionic2+angular2+webpack重构.苦逼的Google了好久,环境搭建还是不太 ...
- (转)windows环境vue+webpack项目搭建
首先,vue.js是一种前端框架,一般利用vue创建项目是要搭配webpack项目构建工具的,而webpack在执行打包压缩的时候是依赖node.js的环境的,所以,要进行vue项目的开发,我们首先要 ...
- vue-cli2.0+webpack 项目搭建
一:准备工作 安装nodejs + 安装webpack + 配置环境变量 => 确保在dos界面的任何路径都都可直接使用命令 二:搭建项目 1.全局安装vue脚手架 [DOS界面] npm i ...
- webpack项目搭建
1.新建一个文件目录,命令行进入当前目录,输入npm init 创建package.json文件 2.安装项目依赖webpack模块: npm install webpack --save-dev 3 ...
- 从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(一)
摘要:随着前端技术的飞速发展,越来越多的技术领域开始被前端工程师踏足.从NodeJs问世至今,各种前端工具脚手架.服务端框架层出不穷,“全栈工程师”对于前端开发者来说,再也不只是说说而已.在NodeJ ...
- 【原创】从零开始搭建Electron+Vue+Webpack项目框架(六)Electron打包,同时构建客户端和web端
导航: (一)Electron跑起来(二)从零搭建Vue全家桶+webpack项目框架(三)Electron+Vue+Webpack,联合调试整个项目(四)Electron配置润色(五)预加载及自动更 ...
- 使用 webpack 手动搭建 vue 项目
webpack 是一个前端工程化打包工具,对于前端工程师来说 webpack 是一项十分重要的技能.下面我们就通过搭建一个 vue 项目来学习使用 webpack 主要环境: node v14.15. ...
- 从零搭建基于webpack的Electron-Vue3项目(1)——基于webpack的Vue3项目搭建
从零搭建基于webpack的Electron-Vue3项目(1)--基于webpack的Vue3项目搭建 前言 本篇文章内容,主要是基于webpack的Vue3项目开发环境进行搭建,暂时还不涉及到El ...
- 搭建自己的Webpack项目
五,搭建自己的Webpack项目 https://www.jianshu.com/p/42e11515c10f
随机推荐
- Mybatis3.2.1整合Spring3.1
Mybatis3.2.1整合Spring3.1 根 据官方的说法,在ibatis3,也就是Mybatis3问世之前,Spring3的开发工作就已经完成了,所以Spring3中还是没有对 Mybatis ...
- el5,6,7的ntpdate服务
在el5里没有ntpdate服务 在el6里有ntpdate服务 在el7里有ntpdate服务
- leetcode-006 detect cycle
package leetcode; public class DetectCycle { public ListNode detectCycle(ListNode head) { ListNode s ...
- Json填充到Form中
很多框架都支持将json解释到grid的或者form中,个人手痒,自己写了一个.所用到的内容主要是javascript对json的遍历.如: for (var key in json) { alert ...
- JS input file 转base64 JS图片预览
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- IOS中APP开发常用的一些接口
免费的API接口: 1.聚合数据,上面有手机归属地查询等: 2.百度API store:上面有很多免费的接口,可以使用在自己的app中: 3.环信:提供一些用户交互的一些场景等,可以用来做即时通讯软件
- Jquery插件之ajaxForm ajaxSubmit的理解用法
如今ajax满天飞,作为重点的form自然也受到照顾. 其实,我们在平常使用Jquery异步提交表单,一般是在submit()中,使用$.ajax进行.比如: $(function(){ $( ...
- ML_note1
Supervised Learning In supervised learning, we are given a data set and already know what our correc ...
- 启动子&外显子&内含子
启动子 http://baike.baidu.com/link?url=HMqaMY4mXusH--4hMu1p6P_XUzEve9lZhFGtxScnbb8Z9HaLYJ981eWxAuZt2iAP ...
- Typescript中的Class
let btn = document.createElement('button'); btn.textContent = 'Say Hello'; document.body.appendChild ...