使用Angular7构建我自己的MEAN堆栈Web应用程序的几乎所有步骤(1)
简而言之
用 Angular7 建立我式的 MEAN 技术栈备忘录。
本次将进行”客户端基础生成”的操作。
先决条件
这是截至2019年1月1日的信息。并且假设以下环境成立。
-
- Angular CLI: 7.0.6
-
- Node.js: 10.15.0
- npm: 6.4.1
另外,假定您对「根目录」、「路由」、「目录」、「组件」、「构建」和「脚本」等词的概念有一定了解。
如果不清楚,请事先简单搜索一下这些词的含义。
(即使您不清楚,按指示进行也能编写出应用程序)
预先准备
请参考「使用 npm 命令安装和升级 Angular CLI 的方法(汇总)」等文章,准备好环境。
以下内容假设您已经能够运行 ng 命令和 npm 命令。
Angular应用程序的初始生成
建立前台基础。
使用Angular CLI进行应用程序自动生成
首先,执行以下命令。
使用 SCSS 生成样式(如果不喜欢,可以选择省略选项)。
# ng new 任意のアプリ名
ng new demo-app --routing=true --style=scss
请确保在执行命令时将“应用程序名称”统一替换。
生成的根目录名称可以更改。
如果在已经克隆了空项目的情况下进行本次生成命令,请将由Angular CLI生成的项目名称目录下的所有文件,除了node_modules和README.md之外,移动或复制到克隆Git目录的根目录。然后删除不需要的目录,并再次运行npm install。
如果指出了脆弱性,就要立即修复。
# 脆弱性に対する対応コマンド
npm audit fix
每次安装npm时,都需要执行这个命令,所以请记住每次都要求它。
将其改为支持PWA
使用以下的 PWA 兼容指令,可以安装 ServiceWorker。
# ng add @angular/pwa --project=アプリ名
ng add @angular/pwa --project=demo-app
当将PWA支持启用后,ngsw-config.json、manifest.json等文件会增加。
因为在使PWA功能时,会利用ServiceWorker来在浏览器中缓存各种内容,如若觉得这让人烦恼的话,可以在启动应用程序之前注释掉PWA功能相关的部分(如src/app/app.module.ts等)。
(※ 为什么会进行缓存,请自行查阅ServiceWorker的相关资料)
实现普遍性
# ng g universal --client-project=アプリ名
ng g universal --client-project=demo-app
在 angular.json 文件中新增一个名为 server 的属性。
追加AppShell
# ng g app-shell --client-project=アプリ名 --universal-project=アプリ名
ng g app-shell --client-project=demo-app --universal-project=demo-app
生成了AppShell的源代码。
(请自行查找AppShell是什么)
引入 Angular Material(可省略)
引入Angular的Material Design。
如果不把Web应用程序设计成Material Design,可以跳过此步骤。
请按照”这篇Qiita文章”中的实际步骤进行安装。
在客户端创建基础
创建一个目录
请在 src/app 目录下创建新的文件夹,内容如下所示。
[ルートディレクトリ]
├─ src
│ └─ app
│ ├─ app-shell # 既存
: ├─ components # 新規作成: コンポーネント用
: :
创建合适的组件
我們需要創建一個適當屏幕級別的組件。
這次我們準備了一個名為 Home 的主屏組件。
# src/app/components ディレクトリに移動
cd src/app/components
# コンポーネント生成 (モジュールが2つあるのでスキップオプションを付けないとエラーになるかも)
ng generate c home --skip-import
当完成后,可以使用 cd ../../.. 命令返回原始的目录位置。
主屏组件修改
在完成的组件中进行以下修正:
向界面中添加测试按钮和按钮按下的处理程序。
首先需要修改 TypeScript。
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
id: number;
name: string;
age: number;
// エラーメッセージ
message: string;
sampleList: { id: number, name: string, age: number }[] = [];
constructor() { }
ngOnInit() {
}
test() {
// エラーメッセージ初期化
this.message = '';
// 入力判定 および 表示処理
if (this.id && this.name && this.age) {
this.sampleList.push({ id: this.id, name: this.name, age: this.age });
} else {
this.message = '未入力の項目があります。必ず全て入力してください';
}
}
// 表示リストをリセット
resetList() {
this.sampleList = [];
}
}
请修正HTML。
<div class="home">
<h2>ホーム画面</h2>
<!--他のコンポーネントに遷移するときに使用 -->
<!-- <a [routerLink]="'/home2'">go to home2</a> -->
<!-- エラーメッセージ -->
<p *ngIf="message" class="error-message">{{ message }}</p>
<!-- 入力エリア -->
<div class="condition">
<label>ユーザID</label>
<input type="number" [(ngModel)]="id">
<label>名前</label>
<input type="text" [(ngModel)]="name">
<label>年齢</label>
<input type="number" [(ngModel)]="age">
<button (click)="test()">表示追加</button>
<button (click)="resetList()">リセット</button>
</div>
<!-- 一覧表示エリア -->
<table>
<thead>
<tr>
<th>ID</th><th>名前</th><th>年齢</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let element of sampleList">
<td>{{ element.id }}</td><td>{{ element.name }}</td><td>{{ element.age }}歳</td>
</tr>
</tbody>
</table>
</div>
然后在CSS中添加。
.home { padding: 1rem }
.error-message { color: red }
.condition { margin: 2rem }
.condition input { margin-right: 1rem }
.condition button { margin-left: 1rem }
table {
width: 100%;
margin: 3rem 0;
}
thead {
color: white;
background-color: #3f51b5;
}
将其添加到模块中
为了启用主屏幕组件,需要将其注册到模块中。
同时,也需要导入Angular所需的模块以处理表单。
:
import { FormsModule } from '@angular/forms'; // 追加
import { HomeComponent } from './components/home/home.component'; // 追加
@NgModule({
declarations: [
AppComponent,
HomeComponent, // 追加
],
imports: [
:
FormsModule, // 追加
],
:
})
export class AppModule { }
添加画面路由
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }, // 追加
{ path: 'home', component: HomeComponent }, // 追加
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
提前导入通用模块。
为了谨慎起见,我会将 module-map-ngfactory-loader 的类型定义文件放在那儿。
npm i -D @nguniversal/module-map-ngfactory-loader
在模块中添加module-map-ngfactory-loader。
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader'; // 追加
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { Routes, RouterModule } from '@angular/router';
import { AppShellComponent } from './app-shell/app-shell.component';
const routes: Routes = [ { path: 'shell', component: AppShellComponent }];
@NgModule({
imports: [
AppModule,
ServerModule,
ModuleMapLoaderModule, // 追加
RouterModule.forRoot(routes),
MatProgressSpinnerModule
],
bootstrap: [AppComponent],
declarations: [AppShellComponent],
})
export class AppServerModule {}
修改应用程序的构建/启动命令
将package.json文件中的脚本部分更改如下:
...
"scripts": {
"ng": "ng",
"dev": "ng serve",
"start": "npx node-static ./dist/demo-app --spa --port=3000",
"build": "npm run build:client",
"build:client": "ng run demo-app:app-shell:production", // ng run アプリ名:app-shell:production
"build:clientsub": "ng build && ng run demo-app:server",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
...
更改接待端口
为了保险起见,在执行ng serve时指定并匹配接受的端口。
angular.json的意思是角度json。
在数据结构中,添加一个端口设置到projects.项目名.架构师.提供的选项中。
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"demo-app": {
:
"architect": {
:
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "demo-app:build", // カンマだけ追加
"port": 3000 // 1行追加
},
"configurations": {
"production": {
"browserTarget": "demo-app:build:production"
}
}
},
:
}
},
:
角度计.js
更改测试时URL的端口号
...
baseUrl: 'http://localhost:3000', // 4200 から修正
...
请稍微确认一下
# ビルド
npm run build
# ビルド終わったら、アプリ起動
npm run start
启动后,通过Web浏览器访问http://localhost:3000 。如果能够确认显示成功,则表示成功(停止请按Ctrl + C)。
只有在AppShell生效时,初次显示界面时会短暂显示AppShellComponent的内容,而且仅限于初次界面显示缓慢的情况。
实际显示的屏幕示例
在浏览器中,初始情况下应该显示如下屏幕。
※ 在图片中,使用 Angular Material 在页眉部分引入了 Material Design。

当你按下“添加显示”按钮而没有输入任何内容时,应该会有这种感觉。

如果您尝试填写输入框并点击“添加显示”按钮,应该会将其添加到列表中。(如果连续快速点击,将会添加很多)

只需要按下”重置”按钮,一切都应该消失。
后端引入准备工作
在做服务器端之前,将客户端相关的目录修改为易于理解的名称。
这次将其修改为”browser”目录。
更改源代码文件夹的名称。
将客户端的目录名称从 src 更改为 browser。
修改 angular.json
在 angular.json 文件中,将 src 替换为 browser。
确认行动
# ビルド
npm run build
# ビルド終わったら、アプリ起動
npm run start
只要正常运行就可以了。
? 请参考以下开发步骤