├── .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 | };
--------------------------------------------------------------------------------