(此文章同時發表在本人微信公眾號“dotNET每日精華文章”,歡迎右邊二維碼來關注。)
題記:兩個還沒有正式發布的東西一起用,是什么效果?
效果當然會很好了(我猜的),那么如何在ASP.NET Core中集成Angular 2呢?Nicolas Bello Camilletti的一篇文章就給大家分享了一些技巧。
作為微軟全新的Web開發框架,ASP.NET Core項目的結構不僅和node.js有幾分神似,也同樣利用了大量的第三方開源工具來輔助客戶端庫的安裝和任務執行,比如npm和bower(用於依賴管理和安裝),gulp用於任務執行。
所以在ASP.NET Core項目中安裝Angular 2也自然而然是通過npm來進行咯。具體步驟如下:
- 通過VS2015或者yeoman新建一個ASP.NET Core的Web項目
- 在VS2015中展開項目下的“Dependencies”,在“npm”上點擊右鍵,選擇“Open package.json”或者直接到項目文件夾里打開package.json文件
- 編輯package.json文件,在devDependencies下面添加“angular2”的配置(我在寫這篇文章的時候,版本號是"2.0.0-beta.9")和“systemjs”(一個輕量級ES6模塊加載器),保存,VS會自動調用npm install來安裝angular及其依賴的包。
- 由於通過npm引入的包,其只會下載到node_modules里面,我們還需要通過gulp任務把所需要的文件copy到wwwroot下才能被瀏覽器訪問到。這個時候,打開gulpfile.js這個文件,在文件末尾添加上下面的代碼:
- 你可以手動通過在gulpfile.js文件上點擊右鍵選擇Task Runner Explorer來執行“copy-deps”,也可以把這個任務添加到project.json中的scripts/prepublish里面。
- 不管采用什么方式,現在在wwwroot/lib/npmlibs下面已經出現了angular2相關的js文件,我們還需要把他們引用到Layout.cshtml中(放到head結束之前):
- 至此,Angular2就添加到ASP.NET Core項目中了。如果你打算用TypeScript來編寫的Angular2代碼,那么還需要額外對TypeScript進行配置:通過VS2015的添加新文件的功能添加一個tsconfig.json文件(TypeScript JSON Configuration File),額外添加修飾聲明,並配置systemjs作為模塊加載器。完整代碼如下:
- 添加TypeScript支持后,你會發現編譯出錯,這是因為沒有引入es6-shim的DefinitelyTyped定義。要引入定義,需要在項目上打開命令行,執行“
npm install tsd --save-dev
”來安裝tsd(TypeScript Definition manager),然后再執行“tsd install es6-shim --save
”來安裝es6-shim的TS定義。這樣就可以解決編譯出錯的問題了。 - 這樣,我們就可以使用TypeScript來編寫Angular2的組件,組件代碼如下(放到wwwroot/app/app.component.ts):
- 在wwwroot/app中添加一個boot.ts文件作為Angular2應用程序的啟動點:
- 然后在視圖中通過systemjs來加載這些組件了(記得先添加<my-app></my-app>這樣的HTML標記,因為我們組件的選擇器是my-app):
- 最后,我們就完成了在ASP.NET Core中開發Angular2應用程序的基本代碼結構了(注意調試的時候不能使用IE,不然會報錯,只能使用Edge或者Chrome之類)。
1: paths.npmSrc = "./node_modules/";
2: paths.npmLibs = paths.webroot + "lib/npmlibs/";
3:
4: gulp.task("copy-deps:systemjs", function () {
5: return gulp.src(paths.npmSrc + '/systemjs/dist/**/*.*', { base: paths.npmSrc + '/systemjs/dist/' })
6: .pipe(gulp.dest(paths.npmLibs + '/systemjs/'));
7: });
8:
9: gulp.task("copy-deps:angular2", function () {
10: return gulp.src(paths.npmSrc + '/angular2/bundles/**/*.js', { base: paths.npmSrc + '/angular2/bundles/' })
11: .pipe(gulp.dest(paths.npmLibs + '/angular2/'));
12: });
13:
14: gulp.task("copy-deps:es6-shim", function () {
15: return gulp.src(paths.npmSrc + '/es6-shim/es6-sh*', { base: paths.npmSrc + '/es6-shim/' })
16: .pipe(gulp.dest(paths.npmLibs + '/es6-shim/'));
17: });
18:
19: gulp.task("copy-deps:rxjs", function () {
20: return gulp.src(paths.npmSrc + '/rxjs/bundles/*.*', { base: paths.npmSrc + '/rxjs/bundles/' })
21: .pipe(gulp.dest(paths.npmLibs + '/rxjs/'));
22: });
23:
24: gulp.task("copy-deps", ["copy-deps:rxjs", 'copy-deps:angular2', 'copy-deps:systemjs', 'copy-deps:es6-shim']);
1: <environment names="Development">
2: <script src="~/lib/npmlibs/es6-shim/es6-shim.js"></script>
3: <script src="~/lib/npmlibs/systemjs/system-polyfills.src.js"></script>
4: <script src="~/lib/npmlibs/angular2/angular2-polyfills.js"></script>
5: <script src="~/lib/npmlibs/systemjs/system.src.js"></script>
6: <script src="~/lib/npmlibs/rxjs/Rx.js"></script>
7: <script src="~/lib/npmlibs/angular2/angular2.js"></script>
8: <script src="~/lib/npmlibs/angular2/router.js"></script>
9: </environment>
10:
11: <environment names="Staging,Production">
12: <script src="~/lib/npmlibs/es6-shim/es6-shim.min.js"></script>
13: <script src="~/lib/npmlibs/systemjs/system-polyfills.js"></script>
14: <script src="~/lib/npmlibs/angular2/angular2-polyfills.min.js"></script>
15: <script src="~/lib/npmlibs/systemjs/system.src.js"></script>
16: <script src="~/lib/npmlibs/rxjs/Rx.min.js"></script>
17: <script src="~/lib/npmlibs/angular2/angular2.min.js"></script>
18: <script src="~/lib/npmlibs/angular2/router.min.js"></script>
19: </environment>
1: {
2: "compilerOptions": {
3: "noImplicitAny": false,
4: "noEmitOnError": true,
5: "removeComments": false,
6: "sourceMap": true,
7: "target": "es5",
8: "emitDecoratorMetadata": true,
9: "experimentalDecorators": true,
10: "module": "system",
11: "moduleResolution": "node"
12: },
13: "exclude": [
14: "node_modules",
15: "wwwroot/lib"
16: ]
17: }
1: import {Component} from 'angular2/core';
2:
3: @Component({
4: selector: 'my-app',
5: template: '<h1>My First Angular 2 App</h1>'
6: })
7: export class AppComponent { }
1: import {bootstrap} from 'angular2/platform/browser'
2: import {AppComponent} from './app.component'
3:
4: bootstrap(AppComponent);
1: @section Scripts {
2: <script>
3: System.config({
4: packages: {
5: 'app': { defaultExtension: 'js' },
6: 'lib': { defaultExtension: 'js' },
7: },
8: });
9:
10: System.import('app/boot')
11: .then(null, console.error.bind(console));
12: </script>
13: }