|
5 | 5 |
|
6 | 6 | - публичный чат https://t.me/angular_universal_ru |
7 | 7 |
|
8 | | -- http://master-ssr.gorniv.com/ - серверный рендеринг master |
9 | | - |
10 | | -- http://master-csr.gorniv.com/ - клиенский рендеринг master |
11 | | - |
12 | | -# Планы: |
13 | | -- [x] Angular 5 |
14 | | -- [x] `document is not defined` и `window is not defined` - [тут](./defined.md) |
15 | | -- [x] [Angular Material2](https://material.angular.io/) **UI компоненты** - [отдельная ветка](https://github.com/Angular-RU/angular-universal-starter/tree/material2) |
16 | | -- [x] [Primeng](https://www.primefaces.org/primeng/) **UI компоненты** - [отдельная ветка](https://github.com/Angular-RU/angular-universal-starter/tree/primeng) |
17 | | -- [x] импорт модулей в зависимости от платформы (`MockServerBrowserModule`) |
18 | | -- [x] выполнение запросов к api на сервере `TransferHttp` |
19 | | -- [x] работа с Cookies на сервере `UniversalStorage` |
20 | | -- [ ] Ionic - необходимо собрать веб версию, пока есть проблемы [отдельная ветка](https://github.com/Angular-RU/angular-universal-starter/tree/ionic) |
21 | | - |
22 | | -## Как запустить |
23 | | -- `yarn` или `npm install` |
24 | | -- `npm run start` - для клиенского рендеринга |
25 | | -- `npm run ssr` - для серверного рендеринга |
26 | | -- `npm run build:universal` - для сборки в релиз |
27 | | -- `npm run server` - для запуска сервера |
28 | | - |
29 | | -## Ссылки |
30 | | -Официальный пример на анлийиском: https://github.com/angular/universal-starter |
31 | | -Модули используемые для universal: |
32 | | -- https://github.com/angular/universal/tree/master/modules/aspnetcore-engine -движок для .net core |
33 | | -- https://github.com/angular/universal/tree/master/modules/common - TransferHttpCacheModule, на данный момент мной не используется, если знаете куда и зачем его встаить - напишите мне или в issue, pull request |
34 | | -- https://github.com/angular/universal/tree/master/modules/express-engine - Express Engine для запуска рендеринга в node, в нашем приложении используется. Обратите внимание, что актуальная версия не ниже 5.0.0-beta.5 |
35 | | -- https://github.com/angular/universal/tree/master/modules/hapi-engine - Hapi Engine альтернативный движок для рендеринга. В примере не используется, принципиально в схеме подключения не отличается от express-engine |
36 | | -- https://github.com/angular/universal/tree/master/modules/module-map-ngfactory-loader - модуль поиска модулей для LazyLoading - вещь нужная и используемая. Обратите внимание, что актуальная версия не ниже 5.0.0-beta.5 |
37 | | - |
38 | | -## Особенности(Важно) |
39 | | -- модуль для TransferHttp использует `import { TransferState } from '@angular/platform-browser';` и необходим для реализации запроса rest api на сервере и остутствия повторного запроса второй раз. Смотрите `home.component.ts` (задержка 3с) |
40 | | - |
41 | | -```ts |
42 | | -this.http.get('https://reqres.in/api/users?delay=3').subscribe(result => { |
43 | | - this.result = result; |
44 | | -}); |
45 | | -``` |
46 | | -- `export const AppRoutes = RouterModule.forRoot(routes, { initialNavigation: 'enabled' });` - чтобы не было мигания страницы! |
47 | | - |
48 | | -- для работы с куками написан `AppStorage`, которыйй при помощи DI позволяет отдавать разную реализацию для сервера и бразуера. Смотрите `server.storage.ts` и `browser.storage.ts` по реализациям. В `server.ts` есть |
49 | | -```ts |
50 | | -providers: [ |
51 | | - { |
52 | | - provide: REQUEST, useValue: (req) |
53 | | - }, |
54 | | - { |
55 | | - provide: RESPONSE, useValue: (res) |
56 | | - } |
57 | | -] |
58 | | -``` |
59 | | -для работы с REQUEST и RESPONSE через DI - это необходимо для реализации UniversalStorage при работе с cookies. |
60 | | - |
61 | | -- webpack.config.js прописан исключительно для сборки файла server.ts в server.js, так как angular-cliт имеет [баг](https://github.com/angular/angular-cli/issues/7200) для работы с 3d зависимостями. |
62 | | -- для решения части проблем используется следущий код в `server.ts` |
63 | | - |
64 | | -Решение проблем глобавльных переменных, в том числе `document is not defined` и `window is not defined` |
65 | | -```ts |
66 | | -const domino = require('domino'); |
67 | | -const fs = require('fs'); |
68 | | -const path = require('path'); |
69 | | -const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString(); |
70 | | -const win = domino.createWindow(template); |
71 | | -const files = fs.readdirSync(`${process.cwd()}/dist-server`); |
72 | | -const styleFiles = files.filter(file => file.startsWith('styles')); |
73 | | -const hashStyle = styleFiles[0].split('.')[1]; |
74 | | -const style = fs.readFileSync(path.join(__dirname, '.', 'dist-server', `styles.${hashStyle}.bundle.css`)).toString(); |
75 | | - |
76 | | -global['window'] = win; |
77 | | -Object.defineProperty(win.document.body.style, 'transform', { |
78 | | - value: () => { |
79 | | - return { |
80 | | - enumerable: true, |
81 | | - configurable: true |
82 | | - }; |
83 | | - }, |
84 | | -}); |
85 | | -global['document'] = win.document; |
86 | | -global['CSS'] = style; |
87 | | -// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest; |
88 | | -global['Prism'] = null; |
89 | | - |
90 | | -``` |
91 | | - |
92 | | -```ts |
93 | | -global['navigator'] = req['headers']['user-agent']; |
94 | | -``` |
95 | | -это позволяет убрать часть проблем при работе с `undefined`. |
96 | | - |
97 | | - |
98 | | - |
| 8 | +- http://material2-ssr.gorniv.com/ - серверный рендеринг material2 |
99 | 9 |
|
| 10 | +- http://material2-csr.gorniv.com/ - клиенский рендеринг material2 |
0 commit comments