|
4 | 4 |
|
5 | 5 | > Repository with Angular CLI and Angular Universal |
6 | 6 |
|
7 | | -- http://material2-ssr.gorniv.com/ - серверный рендеринг material2 |
| 7 | +**Translations**: |
| 8 | +- [Русский](./README-RU.md) |
| 9 | +- [English](./README.md) |
| 10 | +- [Românesc](./README-RO.md) |
8 | 11 |
|
9 | | -- http://material2-csr.gorniv.com/ - клиенский рендеринг material2 |
| 12 | +**Resources**: |
| 13 | +- public chat https://t.me/angular_universal_ru |
| 14 | +- http://master-ssr.gorniv.com/ - server-side rendering of the master |
| 15 | +- http://master-csr.gorniv.com/ - client rendering master |
| 16 | + |
| 17 | +# Plans: |
| 18 | +- [x] Angular 5 |
| 19 | +- [x] `document is not defined` and `window is not defined` - [here](./defined.md) |
| 20 | +- [x] [Angular Material2](https://material.angular.io/) **UI components** - [individual branch](https://github.com/Angular-RU/angular-universal-starter/tree/material2) |
| 21 | +- [x] [Primeng](https://www.primefaces.org/primeng/) **UI components** - [individual branch] (https://github.com/Angular-RU/angular-universal-starter/tree/primeng) |
| 22 | +- [x] modules import depending on the platform (`MockServerBrowserModule`) |
| 23 | +- [x] execution of queries to api on the server `TransferHttp` |
| 24 | +- [x] work with cookies on the server `UniversalStorage` |
| 25 | +- [x] Uses **[ngx-meta](https://github.com/fulls1z3/ngx-meta)** for SEO (*title, meta tags, and Open Graph tags for social sharing*). |
| 26 | +- [x] uses ngx-translate to support internationalization (i18n) |
| 27 | +- [x] uses ORIGIN_URL - for absolute queries |
| 28 | +- [ ] @angular/service-worker |
| 29 | +- [ ] Ionic - it is necessary to compile the web version while there are problems [separate branch](https://github.com/Angular-RU/angular-universal-starter/tree/ionic) |
| 30 | + |
| 31 | +## How to start |
| 32 | +- `yarn` or `npm install` |
| 33 | +- `yarn start` or `npm run start` - for client rendering |
| 34 | +- `yarn ssr` or `npm run ssr` - for server-side rendering |
| 35 | +- `yarn build:universal` or `npm run build:universal` - for assembly in release |
| 36 | +- `yarn server` or `npm run server` - to start the server |
| 37 | +- `yarn build:prerender` or `npm run build:prerender` - to generate static by `static.paths.ts` |
| 38 | +- how to run watch: once: `yarn ssr:cw` or `npm run ssr:cw`, once: `yarn ssr:sw` or `npm run ssr:sw`, after each change: `yarn ssr:server` or `npm run ssr:server` |
| 39 | + |
| 40 | +## How to use this repository in your project: |
| 41 | +To transfer ssr to your repository, you need the following files: |
| 42 | + - .angular-cli.json |
| 43 | + - server.ts |
| 44 | + - prerender.ts |
| 45 | + - webpack.config.js |
| 46 | + - main.server.ts |
| 47 | + - main.browser.ts |
| 48 | + - modules/* |
| 49 | + - forStorage/* |
| 50 | + - environments/* |
| 51 | + - app.browser.module.ts |
| 52 | + - app.server.module.ts |
| 53 | + |
| 54 | +## References |
| 55 | +Official example in English: https://github.com/angular/universal-starter |
| 56 | +Modules used for universal: |
| 57 | +- https://github.com/angular/universal/tree/master/modules/aspnetcore-engine - web for .net core |
| 58 | +- https://github.com/angular/universal/tree/master/modules/common - TransferHttpCacheModule, at the moment I do not use it if you know where and why it should be installed - write to me or in issue, pull request |
| 59 | +- https://github.com/angular/universal/tree/master/modules/express-engine - Express Engine to run the rendering in node, in our application is used. Please note that the current version is not lower than 5.0.0-beta.5 |
| 60 | +- https://github.com/angular/universal/tree/master/modules/hapi-engine - Hapi Engine is an alternative engine for rendering. In the example is not used, in principle in the connection scheme does not differ from express-engine |
| 61 | +- https://github.com/angular/universal/tree/master/modules/module-map-ngfactory-loader - the module search module for LazyLoading - the thing needed and used. Please note that the current version is not lower than 5.0.0-beta.5 |
| 62 | + |
| 63 | +## Features (Important) |
| 64 | +- The module for TransferHttp uses `import {TransferState} from '@angular/platform-browser';` and it is necessary to implement the request rest api on the server and the absence of the second request a second time. See `home.component.ts` (delay 3c) |
| 65 | + |
| 66 | +```ts |
| 67 | +this.http.get('https://reqres.in/api/users?delay=3').subscribe(result => { |
| 68 | + this.result = result; |
| 69 | +}); |
| 70 | +``` |
| 71 | +- `export const AppRoutes = RouterModule.forRoot(routes, { initialNavigation: 'enabled' });`- so that there is no flashing of the page! |
| 72 | + |
| 73 | +- to work with cookies, it is written `AppStorage`, which with DI allows you to give different implementations for the server and the browser. See `server.storage.ts` and `browser.storage.ts` for implementations. In `server.ts` there is |
| 74 | + |
| 75 | +```ts |
| 76 | +providers: [ |
| 77 | + { |
| 78 | + provide: REQUEST, useValue: (req) |
| 79 | + }, |
| 80 | + { |
| 81 | + provide: RESPONSE, useValue: (res) |
| 82 | + } |
| 83 | +] |
| 84 | +``` |
| 85 | +to work with REQUEST and RESPONSE via DI - this is necessary for implementing UniversalStorage when working with cookies. |
| 86 | + |
| 87 | +- `webpack.config.js` is written exclusively for building server.ts file in server.js, since angular-cli has [bug](https: //github.com / angular/angular-cli/issues/7200) to work with 3d dependencies. - To solve some problems, use the following code in `server.ts` Solving the problems of global variables, including `document is not defined` and `window is not defined` |
| 88 | +```ts |
| 89 | +const domino = require('domino'); |
| 90 | +const fs = require('fs'); |
| 91 | +const path = require('path'); |
| 92 | +const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString(); |
| 93 | +const win = domino.createWindow(template); |
| 94 | +const files = fs.readdirSync(`${process.cwd()}/dist-server`); |
| 95 | +// const styleFiles = files.filter(file => file.startsWith('styles')); |
| 96 | +// const hashStyle = styleFiles[0].split('.')[1]; |
| 97 | +// const style = fs.readFileSync(path.join(__dirname, '.', 'dist-server', `styles.${hashStyle}.bundle.css`)).toString(); |
| 98 | + |
| 99 | +global['window'] = win; |
| 100 | +Object.defineProperty(win.document.body.style, 'transform', { |
| 101 | + value: () => { |
| 102 | + return { |
| 103 | + enumerable: true, |
| 104 | + configurable: true |
| 105 | + }; |
| 106 | + }, |
| 107 | +}); |
| 108 | +global['document'] = win.document; |
| 109 | +global['CSS'] = null; |
| 110 | +// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest; |
| 111 | +global['Prism'] = null; |
| 112 | +``` |
| 113 | + |
| 114 | +```ts |
| 115 | + global['navigator'] = req['headers']['user-agent']; |
| 116 | +``` |
| 117 | +this allows you to remove some of the problems when working with `undefined`. |
0 commit comments