Ich arbeite an einem Angular4-Webpack-Projekt, das ich hinzufügen wollte AngularUniversal , um serverseitiges Rendern zu ermöglichen. Die meisten Tutorials verwenden jedoch AngularCli. Ich möchte Universal mit Webpack integrieren. Ich habe Folgendes versucht Tutorial Ohne Glück. Kann jemand bitte helfen.
Diese Angular Universal ist nur für Angular 2. Wenn Sie von vorne anfangen wollen, können Sie diese Angular 4 Universal Seed verwenden Alle Funktionen wie:
Wenn Sie bereits ein Angular 4-Projekt ausgeführt haben, können Sie Universal integrieren, indem Sie folgende Einstellungen in Ihrem Code vornehmen:
Installiere diese Pakete: npm install @angular/{common,compiler,compiler-cli,core,forms,http,platform-browser,platform-browser-dynamic,platform-server,router,animations}@latest [email protected] --save
npm install express @types/express --save-dev
Fügen Sie dies in Ihre Datei app.module.ts ein
import { BrowserModule } from '@angular/platform-browser';
BrowserModule.withServerTransition({
appId: 'my-app-id' // withServerTransition is available only in Angular 4
}),
Erstellen Sie folgende Dateien
src/uni/app.server.ts
import { NgModule } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { ServerModule } from '@angular/platform-server';
import { AppComponent } from '../app/app';
import { AppModule } from '../app/app.module';
import 'reflect-metadata';
import 'zone.js';
@NgModule({
imports: [
ServerModule,
AppModule
],
bootstrap: [
AppComponent
],
providers: [
{provide: APP_BASE_HREF, useValue: '/'}
]
})
export class AppServerModule {
}
src/uni/server-uni.ts
import 'zone.js/dist/zone-node';
import 'zone.js';
import 'reflect-metadata';
import { enableProdMode } from '@angular/core';
import { AppServerModuleNgFactory } from '../../aot/src/uni/app.server.ngfactory';
import * as express from 'express';
import { ngUniversalEngine } from './universal-engine';
enableProdMode();
const server = express();
// set our angular engine as the handler for html files, so it will be used to render them.
server.engine('html', ngUniversalEngine({
bootstrap: [AppServerModuleNgFactory]
}));
// set default view directory
server.set('views', 'src');
// handle requests for routes in the app. ngExpressEngine does the rendering.
server.get(['/', '/dashboard', '/heroes', '/detail/:id'], (req:any, res:any) => {
res.render('index.html', {req});
});
// handle requests for static files
server.get(['/*.js', '/*.css'], (req:any, res:any, next:any) => {
let fileName: string = req.originalUrl;
console.log(fileName);
let root = fileName.startsWith('/node_modules/') ? '.' : 'src';
res.sendFile(fileName, { root: root }, function (err:any) {
if (err) {
next(err);
}
});
});
// start the server
server.listen(3200, () => {
console.log('listening on port 3200...');
});
src/uni/universal-engine.ts
import * as fs from 'fs';
import { renderModuleFactory } from '@angular/platform-server';
const templateCache = {}; // cache for page templates
const outputCache = {}; // cache for rendered pages
export function ngUniversalEngine(setupOptions: any) {
return function (filePath: string, options: { req: Request }, callback: (err: Error, html: string) => void) {
let url: string = options.req.url;
let html: string = outputCache[url];
if (html) {
// return already-built page for this url
console.log('from cache: ' + url);
callback(null, html);
return;
}
console.log('building: ' + url);
if (!templateCache[filePath]) {
let file = fs.readFileSync(filePath);
templateCache[filePath] = file.toString();
}
// render the page via angular platform-server
let appModuleFactory = setupOptions.bootstrap[0];
renderModuleFactory(appModuleFactory, {
document: templateCache[filePath],
url: url
}).then(str => {
outputCache[url] = str;
callback(null, str);
});
};
}
Fügen Sie die Konfiguration in Ihrer Datei tsconfig.ts hinzu, von der ich annehme, dass sie sich im Stammverzeichnis befindet
{
"compilerOptions": {
"baseUrl": "",
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es2016", "dom"],
"moduleResolution": "node",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"target": "es5",
"module": "commonjs",
"types": ["node"],
"typeRoots": [
"node_modules/@types"
]
},
"files": [
"src/uni/app.server.ts",
"src/uni/server-uni.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"entryModule": "./src/app/app.module#AppModule",
"skipMetadataEmit": true
},
"exclude": [
"test.ts",
"**/*.spec.ts"
]
}
Atten Sie Ihre webpack.config.uni.js im Hauptverzeichnis
const ngtools = require('@ngtools/webpack');
const webpack = require('webpack');
const path = require('path');
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin");
module.exports = {
devtool: 'source-map',
entry: {
main: ['./src/uni/app.server.ts', './src/uni/server-uni.ts']
},
resolve: {
extensions: ['.ts', '.js']
},
target: 'node',
output: {
path: path.join(__dirname, "dist"),
filename: 'server.js'
},
plugins: [
new ngtools.AotPlugin({
tsConfigPath: './tsconfig.json'
})
],
module: {
rules: [
{
test: /\.(scss|html|png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
use: 'raw-loader'
},
{ test: /\.ts$/, loader: require.resolve('@ngtools/webpack') },
{
test: /\.(png|jpg|woff|woff2|eot|ttf|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url?limit=512&&name=[path][name].[ext]?[hash]'
},
{ test: /\.scss$/, use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}] }
]
}
}
Fügen Sie unten in Ihrer Datei package.json die folgenden Skripte hinzu:
"ngc-build": "ngc -p ./tsconfig.json", // To generate ngFactory file
"build:uni": "webpack --config webpack.config.uni.js",
"serve:uni": "node dist/server.js",
Es gibt bestimmte Dinge, die wir beachten sollten:
window
, document
, navigator
und andere Browsertypen - sind auf dem Server nicht vorhanden. Die Verwendung dieser oder einer Bibliothek, die sie verwendet (z. B. jQuery), wird nicht funktionieren. In diesem link finden Sie einige Optionen, wenn Sie wirklich etwas von dieser Funktionalität benötigen.Winkeluniversal wird nur für Winkel 2.x verwendet. Angular 4.x müssen Sie den Plattformserver verwenden. Beispiele sind wie folgt:
Für Winkel 2.X.X:
AngularClass's Seed-Projekt mit Express/Universal
https://github.com/angular/universal-starter
Für Winkel 4.X.X Verwenden Sie den Winkelplattformserver
https://github.com/ng-seed/universal
Es gibt auch einige andere Beispiele:
Das in diesem Tutorial erwähnte Beispiel verwendet das im Abschnitt Angular Resources erwähnte Beispiel. Sie haben kürzlich ihre Dokumente aktualisiert und die ausführliche Dokumentation für die Implementierung von @ angle/universal noch nicht bereitgestellt. Diese war früher die Seite, nach der Sie suchen, aber sie hatte einige Probleme hier . Vielleicht haben sie es deshalb entfernt und beschlossen, es neu zu schreiben.
Sie finden ein Angular 4 Tutorial zum serverseitigen Rendern mit Webpack unter this blog .
Eigenschaften:
Das Endergebnis kann auf einem Docker-Host wie folgt angezeigt werden:
(dockerhost)$ docker run -it -p 8002:8000 oveits/angular_hello_world:centos bash
(container)# git clone https://github.com/oveits/ng-universal-demo
(container)# cd ng-universal-demo
(container)# npm i
(container)# npm run start
Ich habe oben Port 8002 ausgewählt, da ich bereits andere Beispiele für die Ports 8000 und 8001 verwende. Wenn der Docker-Host auf Virtualbox ausgeführt wird, benötigen Sie möglicherweise eine Portzuordnung von 8002 des Virtualbox-Hosts zu 8002 der Virtualbox-VM.
Navigieren Sie in einem Browser zu http: // localhost: 8002/blog . Sie sehen den Inhalt eines Blogposts, der von der Wordpress API. Mit Rechtsklick-> Quelltext anzeigen Der HTML-Inhalt wird angezeigt. Dies zeigt, dass es sich um eine serverseitig gerenderte Seite handelt.
PS: Wie das Tutorial, das Sie ausprobiert haben, basiert das Tutorial auf einem Git-Projekt, das ursprünglich von Rob Wormald erstellt wurde , aber mit diesem Fork von FrozenPandaz habe ich Es wurde eine Version gefunden, die auf Angular 4 aktualisiert wurde und besser mit Webpack funktioniert hat (weitere Informationen finden Sie im Anhang von das Blog ).