@tramvai/module-render 2.70.1 → 2.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser.js +9 -233
- package/lib/client/index.browser.js +48 -0
- package/lib/client/renderer.browser.js +50 -0
- package/lib/react/index.browser.js +11 -0
- package/lib/react/index.es.js +11 -0
- package/lib/react/index.js +15 -0
- package/lib/react/pageErrorBoundary.browser.js +23 -0
- package/lib/react/pageErrorBoundary.es.js +23 -0
- package/lib/react/pageErrorBoundary.js +27 -0
- package/lib/react/root.browser.js +58 -0
- package/lib/react/root.es.js +58 -0
- package/lib/react/root.js +62 -0
- package/lib/resourcesInliner/externalFilesHelper.es.js +17 -0
- package/lib/resourcesInliner/externalFilesHelper.js +26 -0
- package/lib/resourcesInliner/fileProcessor.es.js +31 -0
- package/lib/resourcesInliner/fileProcessor.js +40 -0
- package/lib/resourcesInliner/resourcesInliner.es.js +204 -0
- package/lib/resourcesInliner/resourcesInliner.js +213 -0
- package/lib/resourcesInliner/tokens.es.js +15 -0
- package/lib/resourcesInliner/tokens.js +20 -0
- package/lib/resourcesRegistry/index.es.js +28 -0
- package/lib/resourcesRegistry/index.js +36 -0
- package/lib/server/PageBuilder.es.js +93 -0
- package/lib/server/PageBuilder.js +102 -0
- package/lib/server/ReactRenderServer.es.js +90 -0
- package/lib/server/ReactRenderServer.js +98 -0
- package/lib/server/blocks/bundleResource/bundleResource.es.js +62 -0
- package/lib/server/blocks/bundleResource/bundleResource.js +71 -0
- package/lib/server/blocks/polyfill.es.js +35 -0
- package/lib/server/blocks/polyfill.js +39 -0
- package/lib/{server_inline.inline.es.js → server/blocks/preload/onload.inline.es.js} +1 -1
- package/lib/{server_inline.inline.js → server/blocks/preload/onload.inline.js} +2 -0
- package/lib/server/blocks/preload/preloadBlock.es.js +21 -0
- package/lib/server/blocks/preload/preloadBlock.js +30 -0
- package/lib/server/blocks/utils/fetchWebpackStats.es.js +88 -0
- package/lib/server/blocks/utils/fetchWebpackStats.js +115 -0
- package/lib/server/blocks/utils/flushFiles.es.js +33 -0
- package/lib/server/blocks/utils/flushFiles.js +44 -0
- package/lib/server/blocks/utils/requireFunc.es.js +5 -0
- package/lib/server/blocks/utils/requireFunc.js +9 -0
- package/lib/server/constants/performance.es.js +3 -0
- package/lib/server/constants/performance.js +7 -0
- package/lib/server/htmlPageSchema.es.js +33 -0
- package/lib/server/htmlPageSchema.js +37 -0
- package/lib/server/utils.es.js +16 -0
- package/lib/server/utils.js +20 -0
- package/lib/server.es.js +18 -859
- package/lib/server.js +33 -909
- package/lib/shared/LayoutModule.browser.js +40 -0
- package/lib/shared/LayoutModule.es.js +40 -0
- package/lib/shared/LayoutModule.js +42 -0
- package/lib/shared/pageErrorStore.browser.js +19 -0
- package/lib/shared/pageErrorStore.es.js +19 -0
- package/lib/shared/pageErrorStore.js +26 -0
- package/lib/shared/providers.browser.js +18 -0
- package/lib/shared/providers.es.js +18 -0
- package/lib/shared/providers.js +22 -0
- package/package.json +23 -24
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import fetch from 'node-fetch';
|
|
3
|
+
import { requireFunc } from './requireFunc.es.js';
|
|
4
|
+
|
|
5
|
+
let appConfig;
|
|
6
|
+
try {
|
|
7
|
+
appConfig = require('@tramvai/cli/lib/external/config').appConfig;
|
|
8
|
+
}
|
|
9
|
+
catch (e) { }
|
|
10
|
+
let fetchStats = async () => {
|
|
11
|
+
throw new Error(`Unknown environment`);
|
|
12
|
+
};
|
|
13
|
+
if (process.env.NODE_ENV === 'development') {
|
|
14
|
+
fetchStats = async () => {
|
|
15
|
+
const { modern: configModern, staticHost, staticPort, output } = appConfig;
|
|
16
|
+
const getUrl = (filename) => `http://${staticHost}:${staticPort}/${output.client}/${filename}`;
|
|
17
|
+
const request = await fetch(getUrl(configModern ? 'stats.modern.json' : 'stats.json'));
|
|
18
|
+
const stats = await request.json();
|
|
19
|
+
// static - популярная заглушка в env.development.js файлах, надо игнорировать, как было раньше
|
|
20
|
+
const hasAssetsPrefix = process.env.ASSETS_PREFIX && process.env.ASSETS_PREFIX !== 'static';
|
|
21
|
+
const publicPath = hasAssetsPrefix ? process.env.ASSETS_PREFIX : stats.publicPath;
|
|
22
|
+
return {
|
|
23
|
+
...stats,
|
|
24
|
+
publicPath,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (process.env.NODE_ENV === 'test') {
|
|
29
|
+
fetchStats = () => {
|
|
30
|
+
// mock for unit-testing as there is no real static return something just to make server render work
|
|
31
|
+
return Promise.resolve({ publicPath: 'http://localhost:4000/', assetsByChunkName: {} });
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (process.env.NODE_ENV === 'production') {
|
|
35
|
+
const SEARCH_PATHS = [process.cwd(), __dirname];
|
|
36
|
+
const webpackStats = (fileName) => {
|
|
37
|
+
let stats;
|
|
38
|
+
for (const dir of SEARCH_PATHS) {
|
|
39
|
+
try {
|
|
40
|
+
const statsPath = path.resolve(dir, fileName);
|
|
41
|
+
stats = requireFunc(statsPath);
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
// ignore errors as this function is used to load stats for several optional destinations
|
|
46
|
+
// and these destinations may not have stats file
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!stats) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (!process.env.ASSETS_PREFIX) {
|
|
53
|
+
if (process.env.STATIC_PREFIX) {
|
|
54
|
+
throw new Error('Required env variable "ASSETS_PREFIX" is not set. Instead of using "STATIC_PREFIX" env please define "ASSETS_PREFIX: STATIC_PREFIX + /compiled"');
|
|
55
|
+
}
|
|
56
|
+
throw new Error('Required env variable "ASSETS_PREFIX" is not set');
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
...stats,
|
|
60
|
+
publicPath: process.env.ASSETS_PREFIX,
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
const statsLegacy = webpackStats('stats.json');
|
|
64
|
+
const statsModern = webpackStats('stats.modern.json') || statsLegacy;
|
|
65
|
+
if (!statsLegacy) {
|
|
66
|
+
throw new Error(`Cannot find stats.json.
|
|
67
|
+
It should be placed in one of the next places:
|
|
68
|
+
${SEARCH_PATHS.join('\n\t')}
|
|
69
|
+
In case it happens on deployment:
|
|
70
|
+
- In case you are using two independent jobs for building app
|
|
71
|
+
- Either do not split build command by two independent jobs and use one common job with "tramvai build" command without --buildType
|
|
72
|
+
- Or copy stats.json (and stats.modern.json if present) file from client build output to server output by yourself in your CI
|
|
73
|
+
- Otherwise report issue to tramvai team
|
|
74
|
+
In case it happens locally:
|
|
75
|
+
- prefer to use command "tramvai start-prod" to test prod-build locally
|
|
76
|
+
- copy stats.json next to built server.js file
|
|
77
|
+
`);
|
|
78
|
+
}
|
|
79
|
+
fetchStats = (modern) => {
|
|
80
|
+
const stats = modern ? statsModern : statsLegacy;
|
|
81
|
+
return Promise.resolve(stats);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const fetchWebpackStats = async ({ modern, } = {}) => {
|
|
85
|
+
return fetchStats(modern);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export { fetchWebpackStats };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var fetch = require('node-fetch');
|
|
7
|
+
var requireFunc = require('./requireFunc.js');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
|
+
|
|
11
|
+
function _interopNamespace(e) {
|
|
12
|
+
if (e && e.__esModule) return e;
|
|
13
|
+
var n = Object.create(null);
|
|
14
|
+
if (e) {
|
|
15
|
+
Object.keys(e).forEach(function (k) {
|
|
16
|
+
if (k !== 'default') {
|
|
17
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
18
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () { return e[k]; }
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
n["default"] = e;
|
|
26
|
+
return n;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
30
|
+
var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
|
|
31
|
+
|
|
32
|
+
let appConfig;
|
|
33
|
+
try {
|
|
34
|
+
appConfig = require('@tramvai/cli/lib/external/config').appConfig;
|
|
35
|
+
}
|
|
36
|
+
catch (e) { }
|
|
37
|
+
let fetchStats = async () => {
|
|
38
|
+
throw new Error(`Unknown environment`);
|
|
39
|
+
};
|
|
40
|
+
if (process.env.NODE_ENV === 'development') {
|
|
41
|
+
fetchStats = async () => {
|
|
42
|
+
const { modern: configModern, staticHost, staticPort, output } = appConfig;
|
|
43
|
+
const getUrl = (filename) => `http://${staticHost}:${staticPort}/${output.client}/${filename}`;
|
|
44
|
+
const request = await fetch__default["default"](getUrl(configModern ? 'stats.modern.json' : 'stats.json'));
|
|
45
|
+
const stats = await request.json();
|
|
46
|
+
// static - популярная заглушка в env.development.js файлах, надо игнорировать, как было раньше
|
|
47
|
+
const hasAssetsPrefix = process.env.ASSETS_PREFIX && process.env.ASSETS_PREFIX !== 'static';
|
|
48
|
+
const publicPath = hasAssetsPrefix ? process.env.ASSETS_PREFIX : stats.publicPath;
|
|
49
|
+
return {
|
|
50
|
+
...stats,
|
|
51
|
+
publicPath,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (process.env.NODE_ENV === 'test') {
|
|
56
|
+
fetchStats = () => {
|
|
57
|
+
// mock for unit-testing as there is no real static return something just to make server render work
|
|
58
|
+
return Promise.resolve({ publicPath: 'http://localhost:4000/', assetsByChunkName: {} });
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (process.env.NODE_ENV === 'production') {
|
|
62
|
+
const SEARCH_PATHS = [process.cwd(), __dirname];
|
|
63
|
+
const webpackStats = (fileName) => {
|
|
64
|
+
let stats;
|
|
65
|
+
for (const dir of SEARCH_PATHS) {
|
|
66
|
+
try {
|
|
67
|
+
const statsPath = path__namespace.resolve(dir, fileName);
|
|
68
|
+
stats = requireFunc.requireFunc(statsPath);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
// ignore errors as this function is used to load stats for several optional destinations
|
|
73
|
+
// and these destinations may not have stats file
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (!stats) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (!process.env.ASSETS_PREFIX) {
|
|
80
|
+
if (process.env.STATIC_PREFIX) {
|
|
81
|
+
throw new Error('Required env variable "ASSETS_PREFIX" is not set. Instead of using "STATIC_PREFIX" env please define "ASSETS_PREFIX: STATIC_PREFIX + /compiled"');
|
|
82
|
+
}
|
|
83
|
+
throw new Error('Required env variable "ASSETS_PREFIX" is not set');
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
...stats,
|
|
87
|
+
publicPath: process.env.ASSETS_PREFIX,
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
const statsLegacy = webpackStats('stats.json');
|
|
91
|
+
const statsModern = webpackStats('stats.modern.json') || statsLegacy;
|
|
92
|
+
if (!statsLegacy) {
|
|
93
|
+
throw new Error(`Cannot find stats.json.
|
|
94
|
+
It should be placed in one of the next places:
|
|
95
|
+
${SEARCH_PATHS.join('\n\t')}
|
|
96
|
+
In case it happens on deployment:
|
|
97
|
+
- In case you are using two independent jobs for building app
|
|
98
|
+
- Either do not split build command by two independent jobs and use one common job with "tramvai build" command without --buildType
|
|
99
|
+
- Or copy stats.json (and stats.modern.json if present) file from client build output to server output by yourself in your CI
|
|
100
|
+
- Otherwise report issue to tramvai team
|
|
101
|
+
In case it happens locally:
|
|
102
|
+
- prefer to use command "tramvai start-prod" to test prod-build locally
|
|
103
|
+
- copy stats.json next to built server.js file
|
|
104
|
+
`);
|
|
105
|
+
}
|
|
106
|
+
fetchStats = (modern) => {
|
|
107
|
+
const stats = modern ? statsModern : statsLegacy;
|
|
108
|
+
return Promise.resolve(stats);
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const fetchWebpackStats = async ({ modern, } = {}) => {
|
|
112
|
+
return fetchStats(modern);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
exports.fetchWebpackStats = fetchWebpackStats;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import uniq from '@tinkoff/utils/array/uniq';
|
|
2
|
+
import flatten from '@tinkoff/utils/array/flatten';
|
|
3
|
+
|
|
4
|
+
const isJs = (file) => /\.js$/.test(file) && !/\.hot-update\.js$/.test(file);
|
|
5
|
+
const isCss = (file) => /\.css$/.test(file);
|
|
6
|
+
const getFilesByType = (files) => {
|
|
7
|
+
const scripts = files.filter(isJs);
|
|
8
|
+
const styles = files.filter(isCss);
|
|
9
|
+
return {
|
|
10
|
+
scripts,
|
|
11
|
+
styles,
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
const flushFiles = (chunks, webpackStats, { ignoreDependencies = false, } = {}) => {
|
|
15
|
+
// при использовании namedChunkGroups во все entry-файлы как зависимость попадает runtimeChunk
|
|
16
|
+
// что при повторных вызовах flushChunks вызовет дублирование подключения manifest.js
|
|
17
|
+
// из-за чего приложение может запускаться несколько раз
|
|
18
|
+
// без поля namedChunkGroups flushChunks вернет только сами ассеты для чанков, без зависимостей
|
|
19
|
+
const { assetsByChunkName, namedChunkGroups } = webpackStats;
|
|
20
|
+
const resolvedChunks = [];
|
|
21
|
+
for (const chunk of chunks) {
|
|
22
|
+
if (!ignoreDependencies && (namedChunkGroups === null || namedChunkGroups === void 0 ? void 0 : namedChunkGroups[chunk])) {
|
|
23
|
+
resolvedChunks.push(...namedChunkGroups[chunk].chunks);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
resolvedChunks.push(chunk);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const files = flatten(uniq(resolvedChunks).map((chunk) => assetsByChunkName[chunk]));
|
|
30
|
+
return getFilesByType(files);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { flushFiles, isCss, isJs };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var uniq = require('@tinkoff/utils/array/uniq');
|
|
6
|
+
var flatten = require('@tinkoff/utils/array/flatten');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
|
+
|
|
10
|
+
var uniq__default = /*#__PURE__*/_interopDefaultLegacy(uniq);
|
|
11
|
+
var flatten__default = /*#__PURE__*/_interopDefaultLegacy(flatten);
|
|
12
|
+
|
|
13
|
+
const isJs = (file) => /\.js$/.test(file) && !/\.hot-update\.js$/.test(file);
|
|
14
|
+
const isCss = (file) => /\.css$/.test(file);
|
|
15
|
+
const getFilesByType = (files) => {
|
|
16
|
+
const scripts = files.filter(isJs);
|
|
17
|
+
const styles = files.filter(isCss);
|
|
18
|
+
return {
|
|
19
|
+
scripts,
|
|
20
|
+
styles,
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
const flushFiles = (chunks, webpackStats, { ignoreDependencies = false, } = {}) => {
|
|
24
|
+
// при использовании namedChunkGroups во все entry-файлы как зависимость попадает runtimeChunk
|
|
25
|
+
// что при повторных вызовах flushChunks вызовет дублирование подключения manifest.js
|
|
26
|
+
// из-за чего приложение может запускаться несколько раз
|
|
27
|
+
// без поля namedChunkGroups flushChunks вернет только сами ассеты для чанков, без зависимостей
|
|
28
|
+
const { assetsByChunkName, namedChunkGroups } = webpackStats;
|
|
29
|
+
const resolvedChunks = [];
|
|
30
|
+
for (const chunk of chunks) {
|
|
31
|
+
if (!ignoreDependencies && (namedChunkGroups === null || namedChunkGroups === void 0 ? void 0 : namedChunkGroups[chunk])) {
|
|
32
|
+
resolvedChunks.push(...namedChunkGroups[chunk].chunks);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
resolvedChunks.push(chunk);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const files = flatten__default["default"](uniq__default["default"](resolvedChunks).map((chunk) => assetsByChunkName[chunk]));
|
|
39
|
+
return getFilesByType(files);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
exports.flushFiles = flushFiles;
|
|
43
|
+
exports.isCss = isCss;
|
|
44
|
+
exports.isJs = isJs;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { staticRender, dynamicRender } from '@tinkoff/htmlpagebuilder';
|
|
2
|
+
import { ResourceSlot } from '@tramvai/tokens-render';
|
|
3
|
+
import { formatAttributes } from './utils.es.js';
|
|
4
|
+
|
|
5
|
+
const { REACT_RENDER, HEAD_CORE_SCRIPTS, HEAD_DYNAMIC_SCRIPTS, HEAD_META, HEAD_POLYFILLS, HEAD_CORE_STYLES, HEAD_PERFORMANCE, HEAD_ANALYTICS, BODY_START, BODY_END, HEAD_ICONS, BODY_TAIL_ANALYTICS, BODY_TAIL, } = ResourceSlot;
|
|
6
|
+
const htmlPageSchemaFactory = ({ htmlAttrs, }) => {
|
|
7
|
+
return [
|
|
8
|
+
staticRender('<!DOCTYPE html>'),
|
|
9
|
+
staticRender(`<html ${formatAttributes(htmlAttrs, 'html')}>`),
|
|
10
|
+
staticRender('<head>'),
|
|
11
|
+
staticRender('<meta charset="UTF-8">'),
|
|
12
|
+
dynamicRender(HEAD_META),
|
|
13
|
+
dynamicRender(HEAD_PERFORMANCE),
|
|
14
|
+
dynamicRender(HEAD_CORE_STYLES),
|
|
15
|
+
dynamicRender(HEAD_POLYFILLS),
|
|
16
|
+
dynamicRender(HEAD_DYNAMIC_SCRIPTS),
|
|
17
|
+
dynamicRender(HEAD_CORE_SCRIPTS),
|
|
18
|
+
dynamicRender(HEAD_ANALYTICS),
|
|
19
|
+
dynamicRender(HEAD_ICONS),
|
|
20
|
+
staticRender('</head>'),
|
|
21
|
+
staticRender(`<body ${formatAttributes(htmlAttrs, 'body')}>`),
|
|
22
|
+
dynamicRender(BODY_START),
|
|
23
|
+
// react app
|
|
24
|
+
dynamicRender(REACT_RENDER),
|
|
25
|
+
dynamicRender(BODY_END),
|
|
26
|
+
dynamicRender(BODY_TAIL_ANALYTICS),
|
|
27
|
+
dynamicRender(BODY_TAIL),
|
|
28
|
+
staticRender('</body>'),
|
|
29
|
+
staticRender('</html>'),
|
|
30
|
+
];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { htmlPageSchemaFactory };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var htmlpagebuilder = require('@tinkoff/htmlpagebuilder');
|
|
6
|
+
var tokensRender = require('@tramvai/tokens-render');
|
|
7
|
+
var utils = require('./utils.js');
|
|
8
|
+
|
|
9
|
+
const { REACT_RENDER, HEAD_CORE_SCRIPTS, HEAD_DYNAMIC_SCRIPTS, HEAD_META, HEAD_POLYFILLS, HEAD_CORE_STYLES, HEAD_PERFORMANCE, HEAD_ANALYTICS, BODY_START, BODY_END, HEAD_ICONS, BODY_TAIL_ANALYTICS, BODY_TAIL, } = tokensRender.ResourceSlot;
|
|
10
|
+
const htmlPageSchemaFactory = ({ htmlAttrs, }) => {
|
|
11
|
+
return [
|
|
12
|
+
htmlpagebuilder.staticRender('<!DOCTYPE html>'),
|
|
13
|
+
htmlpagebuilder.staticRender(`<html ${utils.formatAttributes(htmlAttrs, 'html')}>`),
|
|
14
|
+
htmlpagebuilder.staticRender('<head>'),
|
|
15
|
+
htmlpagebuilder.staticRender('<meta charset="UTF-8">'),
|
|
16
|
+
htmlpagebuilder.dynamicRender(HEAD_META),
|
|
17
|
+
htmlpagebuilder.dynamicRender(HEAD_PERFORMANCE),
|
|
18
|
+
htmlpagebuilder.dynamicRender(HEAD_CORE_STYLES),
|
|
19
|
+
htmlpagebuilder.dynamicRender(HEAD_POLYFILLS),
|
|
20
|
+
htmlpagebuilder.dynamicRender(HEAD_DYNAMIC_SCRIPTS),
|
|
21
|
+
htmlpagebuilder.dynamicRender(HEAD_CORE_SCRIPTS),
|
|
22
|
+
htmlpagebuilder.dynamicRender(HEAD_ANALYTICS),
|
|
23
|
+
htmlpagebuilder.dynamicRender(HEAD_ICONS),
|
|
24
|
+
htmlpagebuilder.staticRender('</head>'),
|
|
25
|
+
htmlpagebuilder.staticRender(`<body ${utils.formatAttributes(htmlAttrs, 'body')}>`),
|
|
26
|
+
htmlpagebuilder.dynamicRender(BODY_START),
|
|
27
|
+
// react app
|
|
28
|
+
htmlpagebuilder.dynamicRender(REACT_RENDER),
|
|
29
|
+
htmlpagebuilder.dynamicRender(BODY_END),
|
|
30
|
+
htmlpagebuilder.dynamicRender(BODY_TAIL_ANALYTICS),
|
|
31
|
+
htmlpagebuilder.dynamicRender(BODY_TAIL),
|
|
32
|
+
htmlpagebuilder.staticRender('</body>'),
|
|
33
|
+
htmlpagebuilder.staticRender('</html>'),
|
|
34
|
+
];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
exports.htmlPageSchemaFactory = htmlPageSchemaFactory;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const formatAttributes = (htmlAttrs, target) => {
|
|
2
|
+
if (!htmlAttrs) {
|
|
3
|
+
return '';
|
|
4
|
+
}
|
|
5
|
+
const targetAttrs = htmlAttrs.filter((item) => item.target === target);
|
|
6
|
+
const collectedAttrs = targetAttrs.reduce((acc, item) => ({ ...acc, ...item.attrs }), {});
|
|
7
|
+
const attrsString = Object.keys(collectedAttrs).reduce((acc, name) => {
|
|
8
|
+
if (collectedAttrs[name] === true) {
|
|
9
|
+
return `${acc} ${name}`;
|
|
10
|
+
}
|
|
11
|
+
return `${acc} ${name}="${collectedAttrs[name]}"`;
|
|
12
|
+
}, '');
|
|
13
|
+
return attrsString.trim();
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { formatAttributes };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
const formatAttributes = (htmlAttrs, target) => {
|
|
6
|
+
if (!htmlAttrs) {
|
|
7
|
+
return '';
|
|
8
|
+
}
|
|
9
|
+
const targetAttrs = htmlAttrs.filter((item) => item.target === target);
|
|
10
|
+
const collectedAttrs = targetAttrs.reduce((acc, item) => ({ ...acc, ...item.attrs }), {});
|
|
11
|
+
const attrsString = Object.keys(collectedAttrs).reduce((acc, name) => {
|
|
12
|
+
if (collectedAttrs[name] === true) {
|
|
13
|
+
return `${acc} ${name}`;
|
|
14
|
+
}
|
|
15
|
+
return `${acc} ${name}="${collectedAttrs[name]}"`;
|
|
16
|
+
}, '');
|
|
17
|
+
return attrsString.trim();
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
exports.formatAttributes = formatAttributes;
|