├── .gitignore ├── README.md ├── dist ├── app.bundle.js ├── app.js ├── index.html ├── polyfills.js └── vendor.js ├── helpers.js ├── package.json ├── src ├── app │ ├── app.module.ts │ └── components │ │ ├── app.component.ts │ │ └── weui │ │ ├── header.component.ts │ │ └── weui.component.ts ├── index.html ├── main.ts ├── polyfills.ts └── vendor.ts ├── tsconfig.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Create Angular App 2 | 基于 Webpack 自定义 Angular 脚手架 3 | 4 | ```bash 5 | npm i 6 | npm start 7 | ``` 8 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Loading AppComponent content here ... 9 | 10 | 11 | -------------------------------------------------------------------------------- /helpers.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var _root = path.resolve(__dirname, '..'); 3 | function root(args) { 4 | args = Array.prototype.slice.call(arguments, 0); 5 | return path.join.apply(path, [_root].concat(args)); 6 | } 7 | exports.root = root; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-webpack", 3 | "version": "1.0.0", 4 | "description": "A webpack starter for Angular", 5 | "scripts": { 6 | "start": "webpack-dev-server --inline --progress --port 8080", 7 | "test": "karma start", 8 | "build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail" 9 | }, 10 | "license": "MIT", 11 | "dependencies": { 12 | "@angular/common": "~4.2.0", 13 | "@angular/compiler": "~4.2.0", 14 | "@angular/core": "~4.2.0", 15 | "@angular/forms": "~4.2.0", 16 | "@angular/http": "~4.2.0", 17 | "@angular/platform-browser": "~4.2.0", 18 | "@angular/platform-browser-dynamic": "~4.2.0", 19 | "@angular/router": "~4.2.0", 20 | "core-js": "^2.4.1", 21 | "rxjs": "5.0.1", 22 | "zone.js": "^0.8.4" 23 | }, 24 | "devDependencies": { 25 | "@types/jasmine": "2.5.36", 26 | "@types/node": "^6.0.45", 27 | "angular2-template-loader": "^0.6.0", 28 | "awesome-typescript-loader": "^3.0.4", 29 | "css-loader": "^0.26.4", 30 | "extract-text-webpack-plugin": "2.0.0-beta.5", 31 | "file-loader": "^0.9.0", 32 | "html-loader": "^0.4.3", 33 | "html-webpack-plugin": "^2.16.1", 34 | "jasmine-core": "^2.4.1", 35 | "karma": "^1.2.0", 36 | "karma-chrome-launcher": "^2.0.0", 37 | "karma-jasmine": "^1.0.2", 38 | "karma-sourcemap-loader": "^0.3.7", 39 | "karma-webpack": "^2.0.1", 40 | "null-loader": "^0.1.1", 41 | "raw-loader": "^0.5.1", 42 | "rimraf": "^2.5.2", 43 | "style-loader": "^0.13.2", 44 | "ts-loader": "^3.1.1", 45 | "typescript": "~2.3.1", 46 | "webpack": "2.2.1", 47 | "webpack-dev-server": "2.4.1", 48 | "webpack-merge": "^3.0.0", 49 | "weui": "^1.1.2" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | //必需 2 | import { NgModule } from '@angular/core'; 3 | import { BrowserModule } from '@angular/platform-browser'; 4 | 5 | //非必需 6 | //提供ngModel 7 | import { FormsModule } from '@angular/forms'; 8 | //提供路由 9 | import { RouterModule } from "@angular/router"; 10 | 11 | //引入组件 12 | import { AppComponent } from './components/app.component'; 13 | import { WeuiComponent } from './components/weui/weui.component'; 14 | import { HeaderComponent } from './components/weui/header.component'; 15 | 16 | //引入服务 17 | //import { DataService } from './service/data.service'; 18 | //使用路由,并在providers中注入 19 | import { LocationStrategy, HashLocationStrategy } from '@angular/common'; 20 | 21 | //@NgModule装饰器用来为模块定义元数据 22 | @NgModule({ //@NgModule 用来定义模块用的装饰器 23 | imports: [ //需要引入的外部NG模块 24 | //包含了commonModule和applicationModule模块,封装在浏览器平台运行时的一些工具库 25 | BrowserModule, 26 | //表单相关的组件指令等,包含了[(ngModel)] 27 | FormsModule, 28 | //RouterModule.forRoot()方法来创建根路由模块 29 | RouterModule.forRoot([{ 30 | path: 'weui', 31 | component: WeuiComponent 32 | }, { 33 | path: 'header', 34 | component: HeaderComponent 35 | }, { 36 | //默认路由 37 | path: '**', 38 | component: WeuiComponent 39 | }, { 40 | path: '', 41 | redirectTo: '/weui', 42 | pathMatch: 'full' 43 | }]) 44 | //RouterModule.forRoot(routes,{useHash: false}), 45 | ], 46 | //导入模块所依赖的组件、指令等,用于指定这个模块的视图类 47 | //本模块创建的组件,加入到这个元数据中的组件才会被编译 48 | declarations: [AppComponent, WeuiComponent, HeaderComponent], 49 | //全局注入服务 50 | providers: [{ 51 | provide: LocationStrategy, 52 | useClass: HashLocationStrategy 53 | }], 54 | //标记出引导组件 55 | //把这个AppComponent标记为引导 (bootstrap) 组件 56 | //当Angular引导应用时它会在DOM中渲染AppComponent,并把结果放进index.html的元素内部 57 | //声明启动引导哪个组件,必须是编译过的组件 58 | bootstrap: [AppComponent] 59 | }) 60 | export class AppModule {} -------------------------------------------------------------------------------- /src/app/components/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | template: ` 6 |

Hello {{name}}

7 | 8 |

{{num}}

9 | 10 | 11 |

路由

12 | weui 13 | header 14 | 15 | `, 16 | styles: [` 17 | h1{ 18 | color: red 19 | } 20 | `] 21 | }) 22 | export class AppComponent { 23 | num:string = "ABC"; 24 | name = 'Angular'; 25 | testClick(){ 26 | console.log("Wscats") 27 | } 28 | } -------------------------------------------------------------------------------- /src/app/components/weui/header.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { DomSanitizer } from '@angular/platform-browser'; 3 | 4 | @Component({ 5 | selector: 'header-cp', 6 | template: ` 7 |

header

8 | 9 | //驼峰和非驼峰写法均可 10 |

header

11 |

header

12 |
13 |
Var is A
14 |
Var is B
15 |
Var is C
16 |
Var is something else
17 |
18 |
19 | {{我不会被绑定}} 20 |
21 |
22 | `, 23 | styles: [` 24 | .red{ 25 | color: red 26 | } 27 | `] 28 | }) 29 | export class HeaderComponent { 30 | html: any; 31 | constructor(private sanitizer: DomSanitizer) { 32 | this.html = this.sanitizer.bypassSecurityTrustHtml("

要进行转换的内容~

"); 33 | } 34 | myVar: string = "A"; 35 | bool: boolean = true; 36 | testClick() { 37 | this.bool = !this.bool; 38 | }; 39 | /*onInit(): void { 40 | this.html = this.sanitizer.bypassSecurityTrustHtml('

要进行转换的内容

'); 41 | //这里比如返回的一个html内容,或是其它如一张 svg 的图等,用上面代码转一下就可以了,就不会那那个错误了。 42 | }*/ 43 | } -------------------------------------------------------------------------------- /src/app/components/weui/weui.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'weui-cp', 5 | template: ` 6 |

weui

7 | `, 8 | styles: [` 9 | h1{ 10 | color: red 11 | } 12 | `] 13 | }) 14 | export class WeuiComponent { 15 | num:string = "ABC"; 16 | name = 'Angular'; 17 | testClick(){ 18 | console.log("Wscats") 19 | } 20 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 加载中... 10 | 11 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | /*import { enableProdMode } from '@angular/core'; 3 | if (process.env.ENV === 'production') { 4 | enableProdMode(); 5 | }*/ 6 | 7 | //platformBrowserDynamic().bootstrapModule()方法来编译启用AppModule模块 8 | //根据当前的运行环境,如操作系统、浏览器,来初始化一个运行环境,然后从这个环境里面运行AppModule 9 | import { AppModule } from './app/app.module'; 10 | platformBrowserDynamic().bootstrapModule(AppModule); -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | //填充(Polyfills) 2 | //填充包弥合了不同浏览器上的JavaScript实现方面的差异 3 | 4 | //为全局上下文(window)打的补丁,提供了ES2015(ES6)的很多基础特性。 5 | //我们也可以把它换成提供了相同内核API的其它填充库。 6 | //一旦所有的“主流浏览器”都实现了这些API,这个依赖就可以去掉了 7 | import 'core-js/es6'; 8 | import 'core-js/es7/reflect'; 9 | 10 | //一个为Zone规范提供的填充库,该规范已经提交给了TC39委员会,以决定是否要在JavaScript语言中进行标准化 11 | //开发人员应该能在兼容的版本中选择一个喜欢的 zone.js 版本,而不用等Angular升级 12 | //require('zone.js/dist/zone'); 13 | import 'zone.js/dist/zone' 14 | 15 | 16 | /*if (process.env.ENV === 'production') { 17 | // Production 18 | } else { 19 | // Development and test 20 | Error['stackTraceLimit'] = Infinity; 21 | require('zone.js/dist/long-stack-trace-zone'); 22 | }*/ -------------------------------------------------------------------------------- /src/vendor.ts: -------------------------------------------------------------------------------- 1 | //Angular 2 | //这个文件包含Angular所有提供商依赖 3 | //DOM和浏览器相关的每样东西,特别是帮助往DOM中渲染的那部分。 4 | //这个包还包含bootstrapStatic方法,用来引导那些在产品构建时需要离线预编译模板的应用程序 5 | import '@angular/platform-browser'; 6 | 7 | //为应用程序提供一些提供商和bootstrap方法,以便在客户端编译模板。 8 | //不要用于离线编译。 我们使用这个包在开发期间引导应用,以及引导plunker中的范例 9 | import '@angular/platform-browser-dynamic'; 10 | 11 | //存放核心代码,如变化监测机制,依赖注入机制,渲染,装饰器等 12 | //框架中关键的运行期部件,每一个应用都需要它 13 | //包括所有的元数据装饰器:Component、Directive,依赖注入系统,以及组件生命周期钩子 14 | import '@angular/core'; 15 | 16 | //Angular的模板编译器 17 | //它会理解模板,并且把模板转化成代码,以供应用程序运行和渲染 18 | //开发人员通常不会直接跟这个编译器打交道,而是通过platform-browser-dynamic或离线模板编译器间接使用它 19 | //import '@angular/compiler'; 20 | 21 | //提供的服务、管道和指令 22 | import '@angular/common'; 23 | import '@angular/http'; 24 | import '@angular/router'; 25 | 26 | //RxJS 27 | //一个为 可观察对象(Observable)规范 提供的填充库, 28 | //该规范已经提交给了 TC39 委员会,以决定是否要在JavaScript语言中进行标准化 29 | //开发人员应该能在兼容的版本中选择一个喜欢的rxjs版本,而不用等Angular升级 30 | import 'rxjs'; 31 | 32 | // Other vendors for example jQuery, Lodash or Bootstrap 33 | // You can import js, ts, css, sass, ... 34 | 35 | //WeUI 36 | import 'weui'; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs",//组织代码的方式 5 | //"target": "es5",//编译目标平台 6 | "moduleResolution": "node", 7 | "sourceMap": true,//把ts文件变异成js文件时,是否生成对应的SourceMap文件 8 | "emitDecoratorMetadata": true,//让TypeScript支持为带有装饰器的声明生成元数据 9 | "experimentalDecorators": true,//是否启用实验性装饰器特性 10 | "lib": ["es2015", "dom"], 11 | "noImplicitAny": true, 12 | "suppressImplicitAnyIndexErrors": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | //生成入口页面的插件 3 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | //封装好的一个拼接路径的方法,将相对路径转为绝对路径 5 | //var helpers = require('./helpers'); 6 | module.exports = { 7 | //入口文件 8 | entry: { 9 | //运行Angular时所需的一些标准js, 10 | 'polyfills': './src/polyfills.ts', 11 | //文件里面引入了一些第三方的依赖,比如Angular、Lodash、WeUI... 12 | 'vendor': './src/vendor.ts', 13 | 'app': './src/main.ts' 14 | }, 15 | //出口文件 16 | output: { 17 | //helpers.root('dist') 18 | path: __dirname + '/dist', 19 | filename: '[name].js' 20 | }, 21 | module: { 22 | //告诉webpack每一类文件需要使用什么加载器来处理 23 | rules: [{ 24 | //匹配ts后缀的文件 25 | test: /\.ts$/, 26 | //awesome-typescript-loader一个用于把TypeScript代码转译成ES5的加载器,它会由tsconfig.json文件提供指导 27 | //angular2-template-loader用于加载Angular组件的模板和样式 28 | //loaders: ['awesome-typescript-loader', 'angular2-template-loader'] 29 | //ts-loader或者['awesome-typescript-loader', 'angular2-template-loader']均可 30 | loader: 'ts-loader' 31 | },{ 32 | test: /\.css$/, 33 | loader: ['style-loader','css-loader'] 34 | }] 35 | }, 36 | //配置插件 37 | plugins: [ 38 | //压缩js代码 39 | new webpack.optimize.UglifyJsPlugin(), 40 | //Workaround for angular/angular#11580 41 | new webpack.ContextReplacementPlugin( 42 | //The (\\|\/) piece accounts for path separators in *nix and Windows 43 | /angular(\\|\/)core(\\|\/)@angular/, 44 | //可以通过helpers方法来寻找src路径,或者直接用绝对路径来制定上下二选一种写法 45 | __dirname + '/src', 46 | //location of your src 47 | //helpers.root('./src'), 48 | //a map of your routes 49 | {} 50 | ), 51 | //提取公共文件,再编译的时候就可以忽略,提高打包时间,非必需 52 | new webpack.optimize.CommonsChunkPlugin({ 53 | //多个html共用一个js文件,提取公共代码 54 | name: ['app', 'vendor', 'polyfills'] 55 | }), 56 | //自动生成index.html 57 | new HtmlWebpackPlugin({ 58 | //自动向目标index.html文件注入script和link标签 59 | template: './src/index.html', 60 | hash: true 61 | }), 62 | //热替换,非必需 63 | new webpack.HotModuleReplacementPlugin(), 64 | ], 65 | //解析模块路径时的配置 66 | resolve: { 67 | //制定模块的后缀,在引入模块时就会自动补全 68 | extensions: ['.js', '.ts'] 69 | }, 70 | //配置webpack-dev-server 71 | devServer: { 72 | //本地服务器所加载的页面所在的目录 73 | contentBase: "./dist", 74 | //不跳转 75 | historyApiFallback: true, 76 | //设置默认监听端口,如果省略,默认为”8080“ 77 | //port: 8080, 78 | inline: true //实时刷新 79 | } 80 | }; --------------------------------------------------------------------------------