@teambit/preview 0.0.627 → 0.0.632
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/__preview-1643167379538.js +1 -0
- package/dist/artifact-file-middleware.d.ts +12 -0
- package/dist/artifact-file-middleware.js +81 -0
- package/dist/artifact-file-middleware.js.map +1 -0
- package/dist/bundling-strategy.d.ts +6 -1
- package/dist/component-preview.route.d.ts +20 -0
- package/dist/component-preview.route.js +83 -0
- package/dist/component-preview.route.js.map +1 -0
- package/dist/env-preview-template.task.d.ts +42 -0
- package/dist/env-preview-template.task.js +309 -0
- package/dist/env-preview-template.task.js.map +1 -0
- package/dist/env-template.route.d.ts +26 -0
- package/dist/env-template.route.js +89 -0
- package/dist/env-template.route.js.map +1 -0
- package/dist/generate-link.d.ts +1 -1
- package/dist/generate-link.js +3 -3
- package/dist/generate-link.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/preview-artifact.d.ts +2 -0
- package/dist/preview-artifact.js +21 -0
- package/dist/preview-artifact.js.map +1 -1
- package/dist/preview-assets.route.d.ts +19 -0
- package/dist/preview-assets.route.js +66 -0
- package/dist/preview-assets.route.js.map +1 -0
- package/dist/preview-definition.d.ts +16 -3
- package/dist/preview.graphql.d.ts +8 -1
- package/dist/preview.graphql.js +13 -2
- package/dist/preview.graphql.js.map +1 -1
- package/dist/preview.main.runtime.d.ts +78 -11
- package/dist/preview.main.runtime.js +251 -18
- package/dist/preview.main.runtime.js.map +1 -1
- package/dist/preview.preview.runtime.d.ts +11 -2
- package/dist/preview.preview.runtime.js +124 -6
- package/dist/preview.preview.runtime.js.map +1 -1
- package/dist/preview.route.d.ts +3 -7
- package/dist/preview.route.js +22 -21
- package/dist/preview.route.js.map +1 -1
- package/dist/preview.task.d.ts +2 -2
- package/dist/preview.task.js +25 -24
- package/dist/preview.task.js.map +1 -1
- package/dist/strategies/component-strategy.d.ts +52 -12
- package/dist/strategies/component-strategy.js +348 -20
- package/dist/strategies/component-strategy.js.map +1 -1
- package/dist/strategies/env-strategy.d.ts +7 -5
- package/dist/strategies/env-strategy.js +27 -1
- package/dist/strategies/env-strategy.js.map +1 -1
- package/dist/strategies/generate-component-link.d.ts +5 -0
- package/dist/strategies/generate-component-link.js +25 -0
- package/dist/strategies/generate-component-link.js.map +1 -0
- package/dist/types/preview-module.d.ts +1 -0
- package/dist/webpack/html.d.ts +2 -0
- package/dist/webpack/html.js +31 -0
- package/dist/webpack/html.js.map +1 -0
- package/dist/webpack/index.d.ts +1 -0
- package/dist/webpack/index.js +23 -0
- package/dist/webpack/index.js.map +1 -0
- package/package-tar/teambit-preview-0.0.632.tgz +0 -0
- package/package.json +29 -26
- package/preview.main.runtime.tsx +235 -23
- package/preview.preview.runtime.tsx +123 -7
- package/strategies/component-strategy.ts +329 -23
- package/strategies/env-strategy.ts +28 -10
- package/strategies/generate-component-link.ts +19 -0
- package/types/preview-module.ts +2 -0
- package/webpack/html.ts +22 -0
- package/webpack/index.ts +1 -0
- package/package-tar/teambit-preview-0.0.627.tgz +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import PubsubAspect, { PubsubPreview } from '@teambit/pubsub';
|
|
2
2
|
import { Slot, SlotRegistry } from '@teambit/harmony';
|
|
3
3
|
import { ComponentID } from '@teambit/component-id';
|
|
4
|
+
import crossFetch from 'cross-fetch';
|
|
4
5
|
|
|
5
6
|
import { PreviewNotFound } from './exceptions';
|
|
6
7
|
import { PreviewType } from './preview-type';
|
|
@@ -44,7 +45,7 @@ export class PreviewPreview {
|
|
|
44
45
|
/**
|
|
45
46
|
* render the preview.
|
|
46
47
|
*/
|
|
47
|
-
render = () => {
|
|
48
|
+
render = async () => {
|
|
48
49
|
const { previewName, componentId } = this.getLocation();
|
|
49
50
|
const name = previewName || this.getDefault();
|
|
50
51
|
|
|
@@ -52,18 +53,126 @@ export class PreviewPreview {
|
|
|
52
53
|
if (!preview || !componentId) {
|
|
53
54
|
throw new PreviewNotFound(previewName);
|
|
54
55
|
}
|
|
55
|
-
const
|
|
56
|
-
.map((prevName) => {
|
|
56
|
+
const includesAll = await Promise.all(
|
|
57
|
+
(preview.include || []).map(async (prevName) => {
|
|
57
58
|
const includedPreview = this.getPreview(prevName);
|
|
58
59
|
if (!includedPreview) return undefined;
|
|
59
60
|
|
|
60
|
-
return includedPreview.selectPreviewModel?.(
|
|
61
|
+
return includedPreview.selectPreviewModel?.(
|
|
62
|
+
componentId.fullName,
|
|
63
|
+
await this.getPreviewModule(prevName, componentId)
|
|
64
|
+
);
|
|
61
65
|
})
|
|
62
|
-
|
|
66
|
+
);
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
const includes = includesAll.filter((module) => !!module);
|
|
69
|
+
|
|
70
|
+
return preview.render(
|
|
71
|
+
componentId.fullName,
|
|
72
|
+
await this.getPreviewModule(name, componentId),
|
|
73
|
+
includes,
|
|
74
|
+
this.getRenderingContext()
|
|
75
|
+
);
|
|
65
76
|
};
|
|
66
77
|
|
|
78
|
+
async getPreviewModule(name: string, id: ComponentID): Promise<PreviewModule> {
|
|
79
|
+
if (PREVIEW_MODULES[name].componentMap[id.fullName]) return PREVIEW_MODULES[name];
|
|
80
|
+
// if (!window[name]) throw new PreviewNotFound(name);
|
|
81
|
+
// const isSplitComponentBundle = PREVIEW_MODULES[name].isSplitComponentBundle ?? false;
|
|
82
|
+
// const component = window[id.toStringWithoutVersion()];
|
|
83
|
+
const component: any = await this.fetchComponentPreview(id, name);
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
mainModule: PREVIEW_MODULES[name].mainModule,
|
|
87
|
+
componentMap: {
|
|
88
|
+
[id.fullName]: component,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async fetchComponentPreview(id: ComponentID, name: string) {
|
|
94
|
+
let previewFile;
|
|
95
|
+
const allFiles = await this.fetchComponentPreviewFiles(id, name);
|
|
96
|
+
allFiles.forEach((file) => {
|
|
97
|
+
// We want to run the preview file always last
|
|
98
|
+
if (file.endsWith('-preview.js')) {
|
|
99
|
+
previewFile = file;
|
|
100
|
+
} else {
|
|
101
|
+
this.addComponentFileElement(id, file);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const previewScriptElement = this.getPreviewScriptElement(id, name, previewFile, resolve, reject);
|
|
106
|
+
document.head.appendChild(previewScriptElement);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private addComponentFileElement(id: ComponentID, previewBundleFileName: string) {
|
|
111
|
+
if (previewBundleFileName.endsWith('.js')) {
|
|
112
|
+
return this.addComponentFileScriptElement(id, previewBundleFileName);
|
|
113
|
+
}
|
|
114
|
+
return this.addComponentFileLinkElement(id, previewBundleFileName);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private async fetchComponentPreviewFiles(id: ComponentID, previewName: string): Promise<string[]> {
|
|
118
|
+
const previewAssetsRoute = `~aspect/preview-assets`;
|
|
119
|
+
const stringId = id.toString();
|
|
120
|
+
const url = `/api/${stringId}/${previewAssetsRoute}`;
|
|
121
|
+
|
|
122
|
+
const res = await crossFetch(url);
|
|
123
|
+
if (res.status >= 400) {
|
|
124
|
+
throw new PreviewNotFound(previewName);
|
|
125
|
+
}
|
|
126
|
+
const parsed = await res.json();
|
|
127
|
+
if (!parsed.files || !parsed.files.length) {
|
|
128
|
+
throw new PreviewNotFound(previewName);
|
|
129
|
+
}
|
|
130
|
+
return parsed.files;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private addComponentFileScriptElement(id: ComponentID, previewBundleFileName: string) {
|
|
134
|
+
const script = document.createElement('script');
|
|
135
|
+
script.setAttribute('defer', 'defer');
|
|
136
|
+
const stringId = id.toString();
|
|
137
|
+
const previewRoute = `~aspect/component-preview`;
|
|
138
|
+
const src = `/api/${stringId}/${previewRoute}/${previewBundleFileName}`;
|
|
139
|
+
script.src = src;
|
|
140
|
+
document.head.appendChild(script);
|
|
141
|
+
return script;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private addComponentFileLinkElement(id: ComponentID, previewBundleFileName: string) {
|
|
145
|
+
const link = document.createElement('link');
|
|
146
|
+
const stringId = id.toString();
|
|
147
|
+
const previewRoute = `~aspect/component-preview`;
|
|
148
|
+
const href = `/api/${stringId}/${previewRoute}/${previewBundleFileName}`;
|
|
149
|
+
link.setAttribute('href', href);
|
|
150
|
+
if (previewBundleFileName.endsWith('.css')) {
|
|
151
|
+
link.setAttribute('rel', 'stylesheet');
|
|
152
|
+
}
|
|
153
|
+
document.head.appendChild(link);
|
|
154
|
+
return link;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private getPreviewScriptElement(id: ComponentID, name: string, previewBundleFileName: string, resolve, reject) {
|
|
158
|
+
const script = document.createElement('script');
|
|
159
|
+
script.setAttribute('defer', 'defer');
|
|
160
|
+
const stringId = id.toString();
|
|
161
|
+
// const previewRoute = `~aspect/preview`;
|
|
162
|
+
const previewRoute = `~aspect/component-preview`;
|
|
163
|
+
const src = `/api/${stringId}/${previewRoute}/${previewBundleFileName}`;
|
|
164
|
+
script.src = src; // generate path to remote scope. [scope url]/
|
|
165
|
+
script.onload = () => {
|
|
166
|
+
const componentPreview = window[`${id.toStringWithoutVersion()}-preview`];
|
|
167
|
+
if (!componentPreview) return reject(new PreviewNotFound(name));
|
|
168
|
+
const targetPreview = componentPreview[name];
|
|
169
|
+
if (!targetPreview) return reject(new PreviewNotFound(name));
|
|
170
|
+
|
|
171
|
+
return resolve(targetPreview);
|
|
172
|
+
};
|
|
173
|
+
return script;
|
|
174
|
+
}
|
|
175
|
+
|
|
67
176
|
/**
|
|
68
177
|
* register a new preview.
|
|
69
178
|
*/
|
|
@@ -131,6 +240,7 @@ export class PreviewPreview {
|
|
|
131
240
|
const preview = new PreviewPreview(pubsub, previewSlot, renderingContextSlot);
|
|
132
241
|
|
|
133
242
|
window.addEventListener('hashchange', () => {
|
|
243
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
134
244
|
preview.render();
|
|
135
245
|
});
|
|
136
246
|
|
|
@@ -138,9 +248,15 @@ export class PreviewPreview {
|
|
|
138
248
|
}
|
|
139
249
|
}
|
|
140
250
|
|
|
141
|
-
export function linkModules(
|
|
251
|
+
export function linkModules(
|
|
252
|
+
previewName: string,
|
|
253
|
+
defaultModule: any,
|
|
254
|
+
isSplitComponentBundle: boolean,
|
|
255
|
+
componentMap: { [key: string]: any }
|
|
256
|
+
) {
|
|
142
257
|
PREVIEW_MODULES[previewName] = {
|
|
143
258
|
mainModule: defaultModule,
|
|
259
|
+
isSplitComponentBundle,
|
|
144
260
|
componentMap,
|
|
145
261
|
};
|
|
146
262
|
}
|
|
@@ -1,34 +1,340 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { join, resolve, basename } from 'path';
|
|
3
|
+
import { existsSync, mkdirpSync } from 'fs-extra';
|
|
4
|
+
import { Component } from '@teambit/component';
|
|
5
|
+
import { ComponentID } from '@teambit/component-id';
|
|
6
|
+
import { flatten } from 'lodash';
|
|
7
|
+
import { Compiler } from '@teambit/compiler';
|
|
8
|
+
import type { AbstractVinyl } from '@teambit/legacy/dist/consumer/component/sources';
|
|
9
|
+
import type { Capsule } from '@teambit/isolator';
|
|
10
|
+
import { CAPSULE_ARTIFACTS_DIR, ComponentResult } from '@teambit/builder';
|
|
11
|
+
import type { PkgMain } from '@teambit/pkg';
|
|
12
|
+
import { BitError } from '@teambit/bit-error';
|
|
13
|
+
import type { DependencyResolverMain } from '@teambit/dependency-resolver';
|
|
14
|
+
import type { BundlerResult, BundlerContext, Asset, BundlerEntryMap, EntriesAssetsMap } from '@teambit/bundler';
|
|
15
|
+
import { BundlingStrategy, ComputeTargetsContext } from '../bundling-strategy';
|
|
16
|
+
import type { PreviewDefinition } from '../preview-definition';
|
|
17
|
+
import type { ComponentPreviewMetaData, PreviewMain } from '../preview.main.runtime';
|
|
18
|
+
import { generateComponentLink } from './generate-component-link';
|
|
6
19
|
|
|
20
|
+
export const PREVIEW_CHUNK_SUFFIX = 'preview';
|
|
21
|
+
export const COMPONENT_CHUNK_SUFFIX = 'component';
|
|
22
|
+
export const PREVIEW_CHUNK_FILENAME_SUFFIX = `${PREVIEW_CHUNK_SUFFIX}.js`;
|
|
23
|
+
export const COMPONENT_CHUNK_FILENAME_SUFFIX = `${COMPONENT_CHUNK_SUFFIX}.js`;
|
|
24
|
+
|
|
25
|
+
export const COMPONENT_STRATEGY_SIZE_KEY_NAME = 'size';
|
|
26
|
+
export const COMPONENT_STRATEGY_ARTIFACT_NAME = 'preview-component';
|
|
27
|
+
/**
|
|
28
|
+
* bundles all components in a given env into the same bundle.
|
|
29
|
+
*/
|
|
7
30
|
export class ComponentBundlingStrategy implements BundlingStrategy {
|
|
8
31
|
name = 'component';
|
|
9
32
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
33
|
+
constructor(private preview: PreviewMain, private pkg: PkgMain, private dependencyResolver: DependencyResolverMain) {}
|
|
34
|
+
|
|
35
|
+
async computeTargets(context: ComputeTargetsContext, previewDefs: PreviewDefinition[]) {
|
|
36
|
+
const outputPath = this.getOutputPath(context);
|
|
37
|
+
if (!existsSync(outputPath)) mkdirpSync(outputPath);
|
|
38
|
+
|
|
39
|
+
// const entriesArr = flatten(
|
|
40
|
+
// await Promise.all(
|
|
41
|
+
// context.capsuleNetwork.seedersCapsules.map((capsule) => {
|
|
42
|
+
// return this.computeComponentEntry(previewDefs, capsule.component, context);
|
|
43
|
+
// }, {})
|
|
44
|
+
// )
|
|
45
|
+
// );
|
|
46
|
+
|
|
47
|
+
const entriesArr = await Promise.all(
|
|
48
|
+
context.capsuleNetwork.seedersCapsules.map((capsule) => {
|
|
49
|
+
return this.computeComponentEntry(previewDefs, capsule.component, context);
|
|
50
|
+
}, {})
|
|
19
51
|
);
|
|
52
|
+
|
|
53
|
+
const entries: BundlerEntryMap = entriesArr.reduce((entriesMap, entry) => {
|
|
54
|
+
// entriesMap[entry.library.name] = entry;
|
|
55
|
+
Object.assign(entriesMap, entry);
|
|
56
|
+
return entriesMap;
|
|
57
|
+
}, {});
|
|
58
|
+
// const entries = entriesArr.reduce((entriesMap, entry) => {
|
|
59
|
+
// entriesMap[entry.library.name] = entry;
|
|
60
|
+
// return entriesMap;
|
|
61
|
+
// }, {});
|
|
62
|
+
|
|
63
|
+
// const modules = await Promise.all(entriesArr.map(async (entry) => {
|
|
64
|
+
// const dependencies = await this.dependencyResolver.getDependencies(entry.component);
|
|
65
|
+
// const manifest = dependencies.toDependenciesManifest();
|
|
66
|
+
// const peer = Object.entries(manifest.peerDependencies || {}).reduce((acc, [packageName, version]) => {
|
|
67
|
+
// acc[packageName] = {
|
|
68
|
+
// singleton: true,
|
|
69
|
+
// requiredVersion: version
|
|
70
|
+
// };
|
|
71
|
+
|
|
72
|
+
// return acc;
|
|
73
|
+
// }, {});
|
|
74
|
+
// // console.log(entry);
|
|
75
|
+
// return {
|
|
76
|
+
// name: entry.library.name,
|
|
77
|
+
// exposes: {
|
|
78
|
+
// '.': entry.import || ''
|
|
79
|
+
// },
|
|
80
|
+
// shared: {
|
|
81
|
+
// ...manifest.dependencies,
|
|
82
|
+
// ...peer
|
|
83
|
+
// },
|
|
84
|
+
// };
|
|
85
|
+
// }));
|
|
86
|
+
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
// entries: await this.computePaths(outputPath, previewDefs, context),
|
|
90
|
+
entries,
|
|
91
|
+
components: context.components,
|
|
92
|
+
outputPath,
|
|
93
|
+
// modules,
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async computeComponentEntry(previewDefs: PreviewDefinition[], component: Component, context: ComputeTargetsContext) {
|
|
99
|
+
const path = await this.computePaths(previewDefs, context, component);
|
|
100
|
+
const [componentPath] = this.getPaths(context, component, [component.mainFile]);
|
|
101
|
+
const componentPreviewChunkId = this.getComponentChunkId(component.id, 'preview');
|
|
102
|
+
|
|
103
|
+
const entries = {
|
|
104
|
+
[componentPreviewChunkId]: {
|
|
105
|
+
filename: this.getComponentChunkFileName(
|
|
106
|
+
component.id.toString({
|
|
107
|
+
fsCompatible: true,
|
|
108
|
+
ignoreVersion: true,
|
|
109
|
+
}),
|
|
110
|
+
'preview'
|
|
111
|
+
),
|
|
112
|
+
import: path,
|
|
113
|
+
// dependOn: component.id.toStringWithoutVersion(),
|
|
114
|
+
library: {
|
|
115
|
+
name: componentPreviewChunkId,
|
|
116
|
+
type: 'umd',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
if (context.splitComponentBundle) {
|
|
121
|
+
const componentChunkId = component.id.toStringWithoutVersion();
|
|
122
|
+
entries[componentChunkId] = {
|
|
123
|
+
filename: this.getComponentChunkFileName(
|
|
124
|
+
component.id.toString({
|
|
125
|
+
fsCompatible: true,
|
|
126
|
+
ignoreVersion: true,
|
|
127
|
+
}),
|
|
128
|
+
'component'
|
|
129
|
+
),
|
|
130
|
+
import: componentPath,
|
|
131
|
+
library: {
|
|
132
|
+
name: componentChunkId,
|
|
133
|
+
type: 'umd',
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return entries;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private getComponentChunkId(componentId: ComponentID, type: 'component' | 'preview') {
|
|
141
|
+
const id =
|
|
142
|
+
type === 'component'
|
|
143
|
+
? componentId.toStringWithoutVersion()
|
|
144
|
+
: `${componentId.toStringWithoutVersion()}-${PREVIEW_CHUNK_SUFFIX}`;
|
|
145
|
+
return id;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private getComponentChunkFileName(idstr: string, type: 'component' | 'preview') {
|
|
149
|
+
const suffix = type === 'component' ? COMPONENT_CHUNK_FILENAME_SUFFIX : PREVIEW_CHUNK_FILENAME_SUFFIX;
|
|
150
|
+
return `${idstr}-${suffix}`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private getAssetAbsolutePath(context: BundlerContext, asset: Asset): string {
|
|
154
|
+
const path = this.getOutputPath(context);
|
|
155
|
+
return join(path, 'public', asset.name);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
copyAssetsToCapsules(context: BundlerContext, result: BundlerResult) {
|
|
159
|
+
context.components.forEach((component) => {
|
|
160
|
+
const capsule = context.capsuleNetwork.graphCapsules.getCapsule(component.id);
|
|
161
|
+
if (!capsule) return;
|
|
162
|
+
const files = this.findAssetsForComponent(component, result.assets, result.entriesAssetsMap || {});
|
|
163
|
+
if (!files) return;
|
|
164
|
+
|
|
165
|
+
files.forEach((asset) => {
|
|
166
|
+
const filePath = this.getAssetAbsolutePath(context, asset);
|
|
167
|
+
const contents = readFileSync(filePath);
|
|
168
|
+
// const exists = capsule.fs.existsSync(this.getArtifactDirectory());
|
|
169
|
+
// if (!exists) capsule.fs.mkdirSync(this.getArtifactDirectory());
|
|
170
|
+
// We don't use the mkdirSync as it uses the capsule fs which uses memfs, which doesn't know to handle nested none existing folders
|
|
171
|
+
mkdirpSync(join(capsule.path, this.getArtifactDirectory()));
|
|
172
|
+
const filename = basename(asset.name);
|
|
173
|
+
// let filename = asset.name;
|
|
174
|
+
// if (filePath.endsWith('.css')){
|
|
175
|
+
// filename = this.getCssFileName(capsule.component.id);
|
|
176
|
+
// }
|
|
177
|
+
capsule.fs.writeFileSync(join(this.getArtifactDirectory(), filename), contents);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// private getCssFileName(componentId: ComponentID): string {
|
|
183
|
+
// return `${componentId.toString({ ignoreVersion: true, fsCompatible: true })}.css`;
|
|
184
|
+
// }
|
|
185
|
+
|
|
186
|
+
private findAssetsForComponent(
|
|
187
|
+
component: Component,
|
|
188
|
+
assets: Asset[],
|
|
189
|
+
entriesAssetsMap: EntriesAssetsMap
|
|
190
|
+
): Asset[] | undefined {
|
|
191
|
+
if (!assets) return undefined;
|
|
192
|
+
|
|
193
|
+
const componentEntryId = component.id.toStringWithoutVersion();
|
|
194
|
+
const componentPreviewEntryId = this.getComponentChunkId(component.id, 'preview');
|
|
195
|
+
const componentFiles = entriesAssetsMap[componentEntryId]?.assets || [];
|
|
196
|
+
const componentAuxiliaryFiles = entriesAssetsMap[componentEntryId]?.auxiliaryAssets || [];
|
|
197
|
+
const componentPreviewFiles = entriesAssetsMap[componentPreviewEntryId]?.assets || [];
|
|
198
|
+
const componentPreviewAuxiliaryFiles = entriesAssetsMap[componentPreviewEntryId]?.auxiliaryAssets || [];
|
|
199
|
+
|
|
200
|
+
const files = componentFiles
|
|
201
|
+
.concat(componentAuxiliaryFiles)
|
|
202
|
+
.concat(componentPreviewFiles)
|
|
203
|
+
.concat(componentPreviewAuxiliaryFiles);
|
|
204
|
+
return files;
|
|
20
205
|
}
|
|
21
206
|
|
|
22
|
-
|
|
207
|
+
private getArtifactDirectory() {
|
|
208
|
+
return join(CAPSULE_ARTIFACTS_DIR, 'preview');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private computeComponentMetadata(
|
|
212
|
+
context: BundlerContext,
|
|
213
|
+
result: BundlerResult,
|
|
214
|
+
component: Component
|
|
215
|
+
): ComponentPreviewMetaData {
|
|
216
|
+
const componentEntryId = component.id.toStringWithoutVersion();
|
|
217
|
+
if (!result?.entriesAssetsMap || !result?.entriesAssetsMap[componentEntryId]) {
|
|
218
|
+
return {};
|
|
219
|
+
}
|
|
220
|
+
const files = (result.entriesAssetsMap[componentEntryId]?.assets || []).map((file) => {
|
|
221
|
+
return {
|
|
222
|
+
name: basename(file.name),
|
|
223
|
+
size: file.size,
|
|
224
|
+
};
|
|
225
|
+
});
|
|
226
|
+
const filesTotalSize = result.entriesAssetsMap[componentEntryId]?.assetsSize || 0;
|
|
227
|
+
const assets = (result.entriesAssetsMap[componentEntryId]?.auxiliaryAssets || []).map((file) => {
|
|
228
|
+
return {
|
|
229
|
+
name: basename(file.name),
|
|
230
|
+
size: file.size,
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
const assetsTotalSize = result.entriesAssetsMap[componentEntryId]?.auxiliaryAssetsSize || 0;
|
|
234
|
+
const totalSize = filesTotalSize + assetsTotalSize;
|
|
235
|
+
|
|
236
|
+
const metadata = {
|
|
237
|
+
[COMPONENT_STRATEGY_SIZE_KEY_NAME]: {
|
|
238
|
+
files,
|
|
239
|
+
assets,
|
|
240
|
+
totalFiles: filesTotalSize,
|
|
241
|
+
totalAssets: assetsTotalSize,
|
|
242
|
+
total: totalSize,
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
return metadata;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async computeResults(context: BundlerContext, results: BundlerResult[]) {
|
|
249
|
+
const result = results[0];
|
|
250
|
+
|
|
251
|
+
this.copyAssetsToCapsules(context, result);
|
|
252
|
+
|
|
253
|
+
const componentsResults: ComponentResult[] = result.components.map((component) => {
|
|
254
|
+
const metadata = this.computeComponentMetadata(context, result, component);
|
|
255
|
+
return {
|
|
256
|
+
component,
|
|
257
|
+
metadata,
|
|
258
|
+
errors: result.errors.map((err) => (typeof err === 'string' ? err : err.message)),
|
|
259
|
+
warning: result.warnings,
|
|
260
|
+
startTime: result.startTime,
|
|
261
|
+
endTime: result.endTime,
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const artifacts = this.getArtifactDef();
|
|
266
|
+
|
|
23
267
|
return {
|
|
24
|
-
componentsResults
|
|
25
|
-
|
|
26
|
-
errors: result.errors,
|
|
27
|
-
component: result.components[0],
|
|
28
|
-
warning: result.warnings,
|
|
29
|
-
};
|
|
30
|
-
}),
|
|
31
|
-
artifacts: [{ name: 'preview', globPatterns: [previewTask.getPreviewDirectory(context)] }],
|
|
268
|
+
componentsResults,
|
|
269
|
+
artifacts,
|
|
32
270
|
};
|
|
33
271
|
}
|
|
272
|
+
|
|
273
|
+
private getArtifactDef() {
|
|
274
|
+
// eslint-disable-next-line @typescript-eslint/prefer-as-const
|
|
275
|
+
// const env: 'env' = 'env';
|
|
276
|
+
// const rootDir = this.getDirName(context);
|
|
277
|
+
|
|
278
|
+
return [
|
|
279
|
+
{
|
|
280
|
+
name: COMPONENT_STRATEGY_ARTIFACT_NAME,
|
|
281
|
+
globPatterns: ['**'],
|
|
282
|
+
rootDir: this.getArtifactDirectory(),
|
|
283
|
+
// context: env,
|
|
284
|
+
},
|
|
285
|
+
];
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
getDirName(context: ComputeTargetsContext) {
|
|
289
|
+
const envName = context.id.replace('/', '__');
|
|
290
|
+
return `${envName}-preview`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private getOutputPath(context: ComputeTargetsContext) {
|
|
294
|
+
return resolve(`${context.capsuleNetwork.capsulesRootDir}/${this.getDirName(context)}`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private getPaths(context: ComputeTargetsContext, component: Component, files: AbstractVinyl[]) {
|
|
298
|
+
const capsule = context.capsuleNetwork.graphCapsules.getCapsule(component.id);
|
|
299
|
+
if (!capsule) return [];
|
|
300
|
+
const compiler: Compiler = context.env.getCompiler();
|
|
301
|
+
return files.map((file) => join(capsule.path, compiler.getDistPathBySrcPath(file.relative)));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
private getComponentOutputPath(capsule: Capsule) {
|
|
305
|
+
return resolve(`${capsule.path}`);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
private async computePaths(
|
|
309
|
+
defs: PreviewDefinition[],
|
|
310
|
+
context: ComputeTargetsContext,
|
|
311
|
+
component: Component
|
|
312
|
+
): Promise<string> {
|
|
313
|
+
// const previewMain = await this.preview.writePreviewRuntime(context);
|
|
314
|
+
const capsule = context.capsuleNetwork.graphCapsules.getCapsule(component.id);
|
|
315
|
+
// if (!capsule) return undefined;
|
|
316
|
+
if (!capsule)
|
|
317
|
+
throw new BitError(
|
|
318
|
+
`could not find capsule for component ${component.id.toString()} during compute paths to bundle`
|
|
319
|
+
);
|
|
320
|
+
const moduleMapsPromise = defs.map(async (previewDef) => {
|
|
321
|
+
const moduleMap = await previewDef.getModuleMap([component]);
|
|
322
|
+
const maybeFiles = moduleMap.get(component);
|
|
323
|
+
if (!maybeFiles || !capsule) return [];
|
|
324
|
+
const [, files] = maybeFiles;
|
|
325
|
+
const compiledPaths = this.getPaths(context, component, files);
|
|
326
|
+
// const files = flatten(paths.toArray().map(([, file]) => file));
|
|
327
|
+
|
|
328
|
+
return {
|
|
329
|
+
prefix: previewDef.prefix,
|
|
330
|
+
paths: compiledPaths,
|
|
331
|
+
};
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const moduleMaps = flatten(await Promise.all(moduleMapsPromise));
|
|
335
|
+
|
|
336
|
+
const contents = generateComponentLink(moduleMaps);
|
|
337
|
+
return this.preview.writeLinkContents(contents, this.getComponentOutputPath(capsule), 'preview');
|
|
338
|
+
// return flatten(moduleMaps);
|
|
339
|
+
}
|
|
34
340
|
}
|
|
@@ -5,11 +5,12 @@ import { ComponentMap } from '@teambit/component';
|
|
|
5
5
|
import { Compiler } from '@teambit/compiler';
|
|
6
6
|
import { AbstractVinyl } from '@teambit/legacy/dist/consumer/component/sources';
|
|
7
7
|
import { Capsule } from '@teambit/isolator';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { BundlingStrategy } from '../bundling-strategy';
|
|
8
|
+
import { ComponentResult } from '@teambit/builder';
|
|
9
|
+
import { BundlerContext, BundlerHtmlConfig, BundlerResult } from '@teambit/bundler';
|
|
10
|
+
import type { BundlingStrategy, ComputeTargetsContext } from '../bundling-strategy';
|
|
11
11
|
import { PreviewDefinition } from '../preview-definition';
|
|
12
12
|
import { PreviewMain } from '../preview.main.runtime';
|
|
13
|
+
import { html } from '../webpack';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* bundles all components in a given env into the same bundle.
|
|
@@ -19,19 +20,31 @@ export class EnvBundlingStrategy implements BundlingStrategy {
|
|
|
19
20
|
|
|
20
21
|
constructor(private preview: PreviewMain) {}
|
|
21
22
|
|
|
22
|
-
async computeTargets(context:
|
|
23
|
+
async computeTargets(context: ComputeTargetsContext, previewDefs: PreviewDefinition[]) {
|
|
23
24
|
const outputPath = this.getOutputPath(context);
|
|
24
25
|
if (!existsSync(outputPath)) mkdirpSync(outputPath);
|
|
26
|
+
const htmlConfig = this.generateHtmlConfig({ dev: context.dev });
|
|
25
27
|
|
|
26
28
|
return [
|
|
27
29
|
{
|
|
28
30
|
entries: await this.computePaths(outputPath, previewDefs, context),
|
|
31
|
+
html: [htmlConfig],
|
|
29
32
|
components: context.components,
|
|
30
33
|
outputPath,
|
|
31
34
|
},
|
|
32
35
|
];
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
private generateHtmlConfig(options: { dev?: boolean }): BundlerHtmlConfig {
|
|
39
|
+
const config = {
|
|
40
|
+
title: 'Preview',
|
|
41
|
+
templateContent: html('Preview'),
|
|
42
|
+
cache: false,
|
|
43
|
+
minify: options?.dev ?? true,
|
|
44
|
+
};
|
|
45
|
+
return config;
|
|
46
|
+
}
|
|
47
|
+
|
|
35
48
|
async computeResults(context: BundlerContext, results: BundlerResult[]) {
|
|
36
49
|
const result = results[0];
|
|
37
50
|
|
|
@@ -53,7 +66,7 @@ export class EnvBundlingStrategy implements BundlingStrategy {
|
|
|
53
66
|
};
|
|
54
67
|
}
|
|
55
68
|
|
|
56
|
-
private getArtifactDef(context:
|
|
69
|
+
private getArtifactDef(context: ComputeTargetsContext) {
|
|
57
70
|
// eslint-disable-next-line @typescript-eslint/prefer-as-const
|
|
58
71
|
const env: 'env' = 'env';
|
|
59
72
|
const rootDir = this.getDirName(context);
|
|
@@ -68,21 +81,25 @@ export class EnvBundlingStrategy implements BundlingStrategy {
|
|
|
68
81
|
];
|
|
69
82
|
}
|
|
70
83
|
|
|
71
|
-
getDirName(context:
|
|
84
|
+
getDirName(context: ComputeTargetsContext) {
|
|
72
85
|
const envName = context.id.replace('/', '__');
|
|
73
86
|
return `${envName}-preview`;
|
|
74
87
|
}
|
|
75
88
|
|
|
76
|
-
private getOutputPath(context:
|
|
89
|
+
private getOutputPath(context: ComputeTargetsContext) {
|
|
77
90
|
return resolve(`${context.capsuleNetwork.capsulesRootDir}/${this.getDirName(context)}`);
|
|
78
91
|
}
|
|
79
92
|
|
|
80
|
-
private getPaths(context:
|
|
93
|
+
private getPaths(context: ComputeTargetsContext, files: AbstractVinyl[], capsule: Capsule) {
|
|
81
94
|
const compiler: Compiler = context.env.getCompiler();
|
|
82
95
|
return files.map((file) => join(capsule.path, compiler.getDistPathBySrcPath(file.relative)));
|
|
83
96
|
}
|
|
84
97
|
|
|
85
|
-
private async computePaths(
|
|
98
|
+
private async computePaths(
|
|
99
|
+
outputPath: string,
|
|
100
|
+
defs: PreviewDefinition[],
|
|
101
|
+
context: ComputeTargetsContext
|
|
102
|
+
): Promise<string[]> {
|
|
86
103
|
const previewMain = await this.preview.writePreviewRuntime(context);
|
|
87
104
|
const moduleMapsPromise = defs.map(async (previewDef) => {
|
|
88
105
|
const moduleMap = await previewDef.getModuleMap(context.components);
|
|
@@ -102,7 +119,8 @@ export class EnvBundlingStrategy implements BundlingStrategy {
|
|
|
102
119
|
previewDef.prefix,
|
|
103
120
|
paths,
|
|
104
121
|
previewDef.renderTemplatePath ? await previewDef.renderTemplatePath(context) : undefined,
|
|
105
|
-
outputPath
|
|
122
|
+
outputPath,
|
|
123
|
+
false
|
|
106
124
|
);
|
|
107
125
|
|
|
108
126
|
const files = flatten(paths.toArray().map(([, file]) => file)).concat([link]);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { toWindowsCompatiblePath } from '@teambit/toolbox.path.to-windows-compatible-path';
|
|
2
|
+
|
|
3
|
+
export type ModuleVar = {
|
|
4
|
+
prefix: string;
|
|
5
|
+
paths: string[];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function generateComponentLink(modules: ModuleVar[]): string {
|
|
9
|
+
return `${modules
|
|
10
|
+
.map((moduleVar) => {
|
|
11
|
+
return `export const ${moduleVar.prefix} = [${moduleVar.paths
|
|
12
|
+
.map((path) => `require('${toWindowsCompatiblePath(path)}')`)
|
|
13
|
+
.join(', ')}]`;
|
|
14
|
+
|
|
15
|
+
// return `export { * as ${moduleVar.prefix} } from '${toWindowsCompatiblePath(moduleVar.paths)}'`;
|
|
16
|
+
})
|
|
17
|
+
.join('\n')}
|
|
18
|
+
`;
|
|
19
|
+
}
|
package/types/preview-module.ts
CHANGED
package/webpack/html.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** html template for Previews (docs, compositions, etc) */
|
|
2
|
+
export function html(title: string) {
|
|
3
|
+
return `
|
|
4
|
+
<!DOCTYPE html>
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="utf-8">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
9
|
+
<title>${title}</title>
|
|
10
|
+
<script>
|
|
11
|
+
// Allow to use react dev-tools inside the examples
|
|
12
|
+
try { window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__; } catch {}
|
|
13
|
+
</script>
|
|
14
|
+
<!-- minimal css resets -->
|
|
15
|
+
<style> html { height: 100%; } body { margin: 0; height: 100%; } #root { height: 100%; } </style>
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<div id="root"></div>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
21
|
+
`;
|
|
22
|
+
}
|
package/webpack/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { html } from './html';
|