この記事では主に Angular5 のサーバーサイドレンダリングの実践について詳しく説明しますので、参考にしてください。
この記事は、以前の Angular5 の記事に基づいて開発を続けます。上記の記事では、Angular5 Youdao Translation を構築するプロセスと、発生した問題の解決策について説明します。
その後、UI が bootstrap4 から angular マテリアルに変更されました。ここでは、サーバー側のレンダリングは UI の変更とは関係ありません。
これまでの記事を読んでいただいた方は、記事の内容がサーバーサイドレンダリング、vueのnuxt、reactのnextに偏っていることに気づくと思います。
この改訂の前に、時間を大幅に節約できる nuxt.js や next.js などのトップレベルのパッケージ化ライブラリを見つけようとしましたが、役に立ちませんでした。
最終的に、Angular2 から利用可能なフロントエンドとバックエンドの同型ソリューションである Angular Universal (Universal (isomorphic) JavaScript support for Angular.) を使用することにしました
この記事でもドキュメントの内容については詳しく紹介しません。 Angular の SSR へのわかりやすい言語の使用を試みます
前提
以前に作成した udao プロジェクトは、構築からパッケージ化まで完全に angular-cli に準拠しており、この記事は angular5 で構築されたすべてのプロジェクトに共通になります。角度-cli。
構築プロセス
最初にサーバーの依存関係をインストールします
yarn add @angular/platform-server express yarn add -D ts-loader webpack-node-externals npm-run-all
ここで、@angular/platform-server のバージョン番号は、現在の angular バージョンに従ってインストールするのが最適であることに注意してください (例: @angular/platform-)他の依存関係とのバージョンの競合を避けるため、server@5.1.0。
ファイルの作成: src/app/app.server.module.ts
import { NgModule } from '@angular/core' import { ServerModule } from '@angular/platform-server' import { AppModule } from './app.module' import { AppComponent } from './app.component' @NgModule({ imports: [ AppModule, ServerModule ], bootstrap: [AppComponent], }) export class AppServerModule { }
ファイルの更新: src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser' import { NgModule } from '@angular/core' // ... import { AppComponent } from './app.component' // ... @NgModule({ declarations: [ AppComponent // ... ], imports: [ BrowserModule.withServerTransition({ appId: 'udao' }) // ... ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
サーバーモジュールをエクスポートするにはメインファイルが必要です
ファイルの作成: src /main.server.ts
export { AppServerModule } from './app/app.server.module'
それでは @angular/cli.angular-cli.json の設定ファイルを更新しましょう
{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "project": { "name": "udao" }, "apps": [ { "root": "src", "outDir": "dist/browser", "assets": [ "assets", "favicon.ico" ] // ... }, { "platform": "server", "root": "src", "outDir": "dist/server", "assets": [], "index": "index.html", "main": "main.server.ts", "test": "test.ts", "tsconfig": "tsconfig.server.json", "testTsconfig": "tsconfig.spec.json", "prefix": "app", "scripts": [], "environmentSource": "environments/environment.ts", "environments": { "dev": "environments/environment.ts", "prod": "environments/environment.prod.ts" } } ] // ... }
上記の // ... は省略することを意味しますが、json にはコメントがありません。奇妙な....
もちろん、.angular-cli.json の構成は固定されていません。必要に応じて変更できます
サーバーの tsconfig 構成ファイルを作成する必要があります: src/tsconfig.server。 json
{ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/app", "baseUrl": "./", "module": "commonjs", "types": [] }, "exclude": [ "test.ts", "**/*.spec.ts", "server.ts" ], "angularCompilerOptions": { "entryModule": "app/app.server.module#AppServerModule" } }
次に更新します: src /tsconfig.app.json
{ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/app", "baseUrl": "./", "module": "es2015", "types": [] }, "exclude": [ "test.ts", "**/*.spec.ts", "server.ts" ] }
これで、次のコマンドを実行して構成が有効かどうかを確認できます
ng build -prod --build-optimizer --app 0 ng build --aot --app 1
実行結果は下の図のようになります
次に、Express.js サービスを作成し、ファイルを作成します: src/server.ts
import 'reflect-metadata' import 'zone.js/dist/zone-node' import { renderModuleFactory } from '@angular/platform-server' import { enableProdMode } from '@angular/core' import * as express from 'express' import { join } from 'path' import { readFileSync } from 'fs' enableProdMode(); const PORT = process.env.PORT || 4200 const DIST_FOLDER = join(process.cwd(), 'dist') const app = express() const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString() const { AppServerModuleNgFactory } = require('main.server') app.engine('html', (_, options, callback) => { const opts = { document: template, url: options.req.url } renderModuleFactory(AppServerModuleNgFactory, opts) .then(html => callback(null, html)) }); app.set('view engine', 'html') app.set('views', 'src') app.get('*.*', express.static(join(DIST_FOLDER, 'browser'))) app.get('*', (req, res) => { res.render('index', { req }) }) app.listen(PORT, () => { console.log(`listening on http://localhost:${PORT}!`) })
もちろん、server.ts ファイルをパッケージ化するには webpack 構成ファイルが必要です: webpack.config.js
const path = require('path'); var nodeExternals = require('webpack-node-externals'); module.exports = { entry: { server: './src/server.ts' }, resolve: { extensions: ['.ts', '.js'], alias: { 'main.server': path.join(__dirname, 'dist', 'server', 'main.bundle.js') } }, target: 'node', externals: [nodeExternals()], output: { path: path.join(__dirname, 'dist'), filename: '[name].js' }, module: { rules: [ { test: /\.ts$/, loader: 'ts-loader' } ] } }
パッケージ化の便宜上、次のようになります。次のように、数行のスクリプトを package.json に追加するのが最善です:
"scripts": { "ng": "ng", "start": "ng serve", "build": "run-s build:client build:aot build:server", "build:client": "ng build -prod --build-optimizer --app 0", "build:aot": "ng build --aot --app 1", "build:server": "webpack -p", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }
ここで npm run build を実行してみます。次の出力が表示されます:
node ノード dist/server.js ファイルを実行します。パッケージ化されています
http://localhost:4200/ を開くと、プロジェクトのメイン ページが通常どおり表示されます
上から HTML ドキュメントがサーバーから直接レンダリングされていることがわかります。 次に、リクエストを試してみます。データ。
注: このプロジェクトの明示的な (クリック可能なメニュー) ルーティング初期化はデータを要求しませんが、単語の説明の詳細ページは ngOnInit() メソッドでデータを取得します。例: http://localhost:4200/通常のサーバーサイドレンダリングプロジェクトの最初の画面の初期化データのリクエストは、サーバー側とクライアントにそれぞれ一度送信され、サーバー側で実行されません。
問題を発見したら、この落とし穴を解消しましょう
サーバーがデータを取得したかどうかを区別するためにマークが使用されている場合を想像してください。データが取得されていない場合、クライアントはそれを要求します。 . データが取得されている場合、リクエストは送信されません
もちろん、Angular には Transfer State 用の Angular Modules が用意されています
では、実際にどのように使用するのでしょうか。以下を参照してください
ピットを埋めるリクエスト
サーバーの入り口とクライアントの入り口にそれぞれTransferStateModuleを導入してください
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server'; // ... @NgModule({ imports: [ // ... ServerModule, ServerTransferStateModule ] // ... }) export class AppServerModule { } import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser'; // ... @NgModule({ declarations: [ AppComponent // ... ], imports: [ BrowserModule.withServerTransition({ appId: 'udao' }), BrowserTransferStateModule // ... ] // ... }) export class AppModule { }
このプロジェクトを例として、detail.component.tsを次のように変更してください
import { Component, OnInit } from '@angular/core' import { HttpClient } from '@angular/common/http' import { Router, ActivatedRoute, NavigationEnd } from '@angular/router' import { TransferState, makeStateKey } from '@angular/platform-browser' const DETAIL_KEY = makeStateKey('detail') // ... export class DetailComponent implements OnInit { details: any // some variable constructor( private http: HttpClient, private state: TransferState, private route: ActivatedRoute, private router: Router ) {} transData (res) { // translate res data } ngOnInit () { this.details = this.state.get(DETAIL_KEY, null as any) if (!this.details) { this.route.params.subscribe((params) => { this.loading = true const apiURL = `https://dict.youdao.com/jsonapi?q=${params['word']}` this.http.get(`/?url=${encodeURIComponent(apiURL)}`) .subscribe(res => { this.transData(res) this.state.set(DETAIL_KEY, res as any) this.loading = false }) }) } else { this.transData(this.details) } } }
コードはシンプルで、十分明確であり、上で説明したとおりです。原理は同じです
ここで、DOMContentLoaded 時にコードを実行して TransferState が適切に動作するように、main.ts ファイルを少し調整するだけです:
import { enableProdMode } from '@angular/core' import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { AppModule } from './app/app.module' import { environment } from './environments/environment' if (environment.production) { enableProdMode() } document.addEventListener('DOMContentLoaded', () => { platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.log(err)) })
ここに移動して npm を実行しますbuild && node dist/server.js を実行してから、コンソールで http://localhost:4200/detail/add を更新して、次のようにネットワークを表示します:
XHR カテゴリでリクエストが開始されていないことがわかります。 Service-Worker のキャッシュのみがヒットします。
これまでのところ、プロジェクトはすべて正常に実行されており、他のバグは見つかっていません。
概要
2018 年の最初の記事の目的は、すべての人気フレームワークにおけるサーバーサイド レンダリングの実装を調査し、最後まで試されなかったフレームワークである Angular をオープンすることです。
もちろん、Orange はまだフロントエンドの小学生です。実装方法はあまり明確ではありません。間違いがある場合は、それを理解していただければ幸いです。私を啓発します。
最後のGithubアドレスは前回の記事と同じです: https://github.com/OrangeXC/udao
以上は皆さんのためにまとめたもので、今後皆さんのお役に立てれば幸いです。
関連記事:
以上がAngular5 を使用してサーバー側レンダリングの実践を実装するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

JavaScript文字列置換法とFAQの詳細な説明 この記事では、javaScriptの文字列文字を置き換える2つの方法について説明します:内部JavaScriptコードとWebページの内部HTML。 JavaScriptコード内の文字列を交換します 最も直接的な方法は、置換()メソッドを使用することです。 str = str.replace( "find"、 "置換"); この方法は、最初の一致のみを置き換えます。すべての一致を置き換えるには、正規表現を使用して、グローバルフラグGを追加します。 str = str.replace(/fi

単純なJavaScript関数は、日付が有効かどうかを確認するために使用されます。 関数isvaliddate(s){ var bits = s.split( '/'); var d = new Date(bits [2] '/' bits [1] '/'ビット[0]); return !!(d &&(d.getmonth()1)== bits [1] && d.getdate()== number(bits [0])); } //テスト var

この記事では、jQueryを使用して、DOM要素の内側のマージン値とマージン値、特に外側の縁と要素の内側の縁の特定の位置を取得して設定する方法について説明します。 CSSを使用して要素の内側と外側の縁を設定することは可能ですが、正確な値を取得するのは難しい場合があります。 // 設定 $( "div.header")。css( "margin"、 "10px"); $( "div.header")。css( "padding"、 "10px"); このコードはそうだと思うかもしれません

この記事では、10個の例外的なjQueryタブとアコーディオンについて説明します。 タブとアコーディオンの重要な違いは、コンテンツパネルの表示方法と非表示にあります。これらの10の例を掘り下げましょう。 関連記事:10 jQueryタブプラグイン

ウェブサイトのダイナミズムと視覚的な魅力を高めるために、10の例外的なjQueryプラグインを発見してください!このキュレーションされたコレクションは、画像アニメーションからインタラクティブなギャラリーまで、多様な機能を提供します。これらの強力なツールを探りましょう。 関連投稿: 1

HTTP-Consoleは、HTTPコマンドを実行するためのコマンドラインインターフェイスを提供するノードモジュールです。 Webサーバー、Web Servに対して作成されているかどうかに関係なく、HTTPリクエストで何が起こっているかをデバッグして正確に確認するのに最適です

このチュートリアルでは、カスタムGoogle検索APIをブログまたはWebサイトに統合する方法を示し、標準のWordPressテーマ検索関数よりも洗練された検索エクスペリエンスを提供します。 驚くほど簡単です!検索をyに制限することができます

次のjQueryコードスニペットを使用して、Divコンテンツがコンテナ要素領域を超えたときにスクロールバーを追加できます。 (デモンストレーションはありません、それを直接firebugにコピーしてください) // d =ドキュメント // w =ウィンドウ // $ = jQuery var contentarea = $(this)、 wintop = contentarea.scrolltop()、 docheight = $(d).height()、 winheight = $(w).height()、 divheight = $( '#c


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SublimeText3 中国語版
中国語版、とても使いやすい

メモ帳++7.3.1
使いやすく無料のコードエディター

Dreamweaver Mac版
ビジュアル Web 開発ツール
