Skip to content

Commit 897b415

Browse files
committed
add chunks tracking
1 parent 174ec54 commit 897b415

File tree

8 files changed

+93
-25
lines changed

8 files changed

+93
-25
lines changed

__tests__/utils.spec.ts

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,32 @@ import {remapImports} from "../src/scanners/scanForImports";
22
import {dirname} from "path";
33

44
describe('scanForImports', () => {
5-
const rel = '.'+dirname(__dirname);
5+
const rel = '.' + dirname(__dirname);
6+
const root = '.';
67

78
it('should map simple import', () => {
89
const imports = {};
910
remapImports(
1011
[{file: 'a', content: 'blabla;import("./a.js"); blabla;'}],
11-
'.', '.',
12+
root, root,
1213
(a, b) => a + b,
1314
imports
1415
);
1516
expect(Object.values(imports)).toEqual([
16-
`() => import('${rel}/a.js')`
17+
`() => [import('${rel}/a.js'), '', '${rel}/a.js']`
1718
]);
1819
});
1920

2021
it('should map simple import with a comment', () => {
2122
const imports = {};
2223
remapImports(
2324
[{file: 'a', content: 'blabla;import(/* comment:42 */"./a.js"); blabla;'}],
24-
'.', '.',
25+
root, root,
2526
(a, b) => a + b,
2627
imports
2728
);
2829
expect(Object.values(imports)).toEqual([
29-
`() => import(/* comment:42 */'${rel}/a.js')`
30+
`() => [import(/* comment:42 */'${rel}/a.js'), '', '${rel}/a.js']`
3031
]);
3132
});
3233

@@ -37,15 +38,32 @@ describe('scanForImports', () => {
3738
file: 'a',
3839
content: 'blabla;import(/* webpack: "123" */"./a.js"); blabla; import(/* webpack: 123 */ \'./b.js\');'
3940
}],
40-
'.', '.',
41+
root, root,
4142
(a, b) => a + b,
4243
imports
4344
);
4445
expect(Object.values(imports)).toEqual([
45-
`() => import(/* webpack: \"123\" */'${rel}/a.js')`,
46-
`() => import(/* webpack: 123 */'${rel}/b.js')`,
46+
`() => [import(/* webpack: \"123\" */'${rel}/a.js'), '', '${rel}/a.js']`,
47+
`() => [import(/* webpack: 123 */'${rel}/b.js'), '', '${rel}/b.js']`,
4748
]);
48-
})
49+
});
50+
51+
it('should match chunk name', () => {
52+
const imports = {};
53+
remapImports(
54+
[{
55+
file: 'a',
56+
content: 'blabla;import(/* webpackChunkName: "chunk-a" */"./a.js"); blabla; import(/* webpack: 123 */ \'./b.js\');'
57+
}],
58+
root, root,
59+
(a, b) => a + b,
60+
imports
61+
);
62+
expect(Object.values(imports)).toEqual([
63+
`() => [import(/* webpackChunkName: "chunk-a" */'${rel}/a.js'), 'chunk-a', '${rel}/a.js']`,
64+
`() => [import(/* webpack: 123 */'${rel}/b.js'), '', '${rel}/b.js']`,
65+
]);
66+
});
4967

5068
it('should remove webpackPrefetch and webpackPreload', () => {
5169
const imports = {};
@@ -54,13 +72,13 @@ describe('scanForImports', () => {
5472
file: 'a',
5573
content: 'blabla;import(/* webpackPrefetch: true *//* webpack: "123" */"./a.js"); blabla; import(/* webpackPreload: true */ \'./b.js\');'
5674
}],
57-
'.', '.',
75+
root, root,
5876
(a, b) => a + b,
5977
imports
6078
);
6179
expect(Object.values(imports)).toEqual([
62-
`() => import(/* *//* webpack: \"123\" */'${rel}/a.js')`,
63-
`() => import(/* */'${rel}/b.js')`,
80+
`() => [import(/* *//* webpack: \"123\" */'${rel}/a.js'), '', '${rel}/a.js']`,
81+
`() => [import(/* */'${rel}/b.js'), '', '${rel}/b.js']`,
6482
]);
6583
});
6684
});

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import LazyBoundary from './LazyBoundary'
1212
import {setConfiguration} from './config';
1313
import {remapImports} from './helpers';
1414

15-
import {useImported, useLoadable, useLazy} from './useImported'
15+
import {useImported, useLoadable, useLazy} from './useImported';
1616

1717
export {
1818
printDrainHydrateMarks,

src/loadable.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {assingLoadableMark} from './marks';
22
import {isBackend} from './detectBackend';
3-
import {DefaultImport, Loadable, Promised} from './types';
3+
import {DefaultImport, Loadable, Mark, MarkMeta, Promised} from './types';
44

55
type AnyFunction = (x: any) => any;
66

@@ -18,7 +18,7 @@ const addPending = (promise: Promise<any>) => pending.push(promise);
1818
const removeFromPending = (promise: Promise<any>) => pending = pending.filter(a => a !== promise);
1919
const trimImport = (str: string) => str.replace(/['"]/g, '');
2020

21-
export const importMatch = (functionString: string) => {
21+
export const importMatch = (functionString: string): Mark => {
2222
const markMatches = functionString.match(/`imported_(.*?)_component`/g) || [];
2323
return markMatches
2424
.map(match => match && trimImport((match.match(/`imported_(.*?)_component`/i) || [])[1]));
@@ -174,9 +174,21 @@ export const dryRender = (renderFunction: () => void) => {
174174
.then(done);
175175
};
176176

177-
export const assignImportedComponents = (set: Array<Promised<any>>) => {
177+
export const markMeta: MarkMeta[] = [];
178+
179+
const assignMetaData = (mark: Mark, chunkName: string, fileName: string) => {
180+
markMeta.push({mark, chunkName, fileName});
181+
};
182+
183+
type ImportedDefinition = [Promised<any>, string, string]
184+
185+
export const assignImportedComponents = (set: Array<ImportedDefinition>) => {
178186
const countBefore = LOADABLE_SIGNATURE.size;
179-
set.forEach(imported => toLoadable(imported));
187+
set.forEach(imported => {
188+
const loadable = toLoadable(imported[0]);
189+
assignMetaData(loadable.mark, imported[1], imported[2]);
190+
});
191+
180192
if (countBefore === LOADABLE_SIGNATURE.size) {
181193
console.error('react-imported-component: no import-marks found, please check babel plugin')
182194
}

src/markerMapper.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {Mark, MarkMeta} from "./types";
2+
import {markMeta} from "./loadable";
3+
import {markerOverlap} from "./marks";
4+
5+
const getMarkedMeta = (marks: Mark, mapping: (meta: MarkMeta) => string) => (
6+
(new Set(
7+
markMeta
8+
.filter(meta => markerOverlap(meta.mark, marks))
9+
.map(mapping)
10+
.filter(Boolean)
11+
)).values()
12+
);
13+
14+
export const getMarkedChunks = (marks: Mark) => getMarkedMeta(marks, meta => meta.chunkName);
15+
export const getMarkedFileNames = (marks: Mark) => getMarkedMeta(marks, meta => meta.fileName);

src/marks.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export const drainHydrateMarks = (stream: Stream = defaultStream) => {
5252
};
5353

5454

55-
const allIn = (a1: string[], a2: string[]) => a1.filter(mark => a2.indexOf(mark) >= 0).length === a1.length;
55+
export const markerOverlap = (a1: string[], a2: string[]) => a1.filter(mark => a2.indexOf(mark) >= 0).length === a1.length;
5656

5757
export const rehydrateMarks = (marks?: string[]) => {
5858
const rehydratedMarks: string[] = marks || (global as any).___REACT_DEFERRED_COMPONENT_MARKS || [];
@@ -62,7 +62,7 @@ export const rehydrateMarks = (marks?: string[]) => {
6262

6363
LOADABLE_MARKS
6464
.forEach(({mark, loadable}) => {
65-
if (allIn(mark, rehydratedMarks)) {
65+
if (markerOverlap(mark, rehydratedMarks)) {
6666
mark.forEach(m => usedMarks.add(m));
6767
tasks.push(loadable.load())
6868
}
@@ -82,7 +82,7 @@ export const waitForMarks = (marks: string[]) => {
8282

8383
LOADABLE_MARKS
8484
.forEach(({mark, loadable}) => {
85-
if (allIn(mark, marks)) {
85+
if (markerOverlap(mark, marks)) {
8686
tasks.push(loadable.resolution)
8787
}
8888
});

src/scanners/scanForImports.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ const trimImport = (str: string) => str.replace(/['"]/g, '');
1414
const getImports = getMatchString(`(['"]?[\\w-/.]+['"]?)\\)`, 1);
1515
const getComment = getMatchString(/\/\*.*\*\// as any, 0);
1616

17-
const clearComment = (str:string) => (
17+
const getChunkName = getMatchString('webpackChunkName: "([^"]*)"', 1);
18+
19+
const clearComment = (str: string) => (
1820
str
1921
.replace("webpackPrefetch: true", '')
2022
.replace("webpackPreload: true", '')
@@ -64,12 +66,24 @@ const rejectSystemFiles = (file: string, stats: Stats) => (
6466
stats.isDirectory() && file.match(/node_modules/) || file.match(/(\/\.\w+)/)
6567
);
6668

67-
export const remapImports = (data: FileContent[], root: string, targetDir: string, getRelative: (a: string, b: string) => string, imports: Record<string, string>) => (
69+
export const remapImports = (
70+
data: FileContent[],
71+
root: string,
72+
targetDir: string,
73+
getRelative: (a: string, b: string) => string,
74+
imports: Record<string, string>,
75+
) => (
6876
data
6977
.map(({file, content}) => mapImports(file, getDynamicImports(content)))
70-
.forEach(importBlock => importBlock.forEach(({name, comment, doNotTransform}) => {
71-
imports[getRelative(root, name)] = `() => import(${comment}'${doNotTransform ? name : getRelative(targetDir, name)}')`
72-
}))
78+
.forEach(importBlock => (
79+
importBlock
80+
.forEach(({name, comment, doNotTransform}) => {
81+
const rootName = doNotTransform ? name : getRelative(root, name);
82+
const fileName = doNotTransform ? name : getRelative(targetDir, name);
83+
84+
imports[getRelative(root, name)] = `() => [import(${comment}'${fileName}'), '${getChunkName(comment)}', '${rootName}']`
85+
})
86+
))
7387
);
7488

7589
function scanTop(root: string, start: string, target: string) {

src/server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {ImportedStream} from './context';
33
import {setConfiguration} from './config';
44
import {createLoadableTransformer} from './transformers/loadableTransformer';
55
import {getLoadableTrackerCallback} from './trackers/globalTracker';
6+
import {getMarkedChunks, getMarkedFileNames} from './markerMapper';
67

78
export {
89
printDrainHydrateMarks,
@@ -14,4 +15,7 @@ export {
1415
createLoadableStream,
1516
createLoadableTransformer,
1617
getLoadableTrackerCallback,
18+
19+
getMarkedChunks,
20+
getMarkedFileNames,
1721
}

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ export type DefaultComponentImport<T> = () => Promise<DefaultComponent<T>>
2323
export type Defaultable<P> = P | Default<P>;
2424
export type DefaultImport<T> = () => Promise<Defaultable<T>>
2525

26+
export interface MarkMeta {
27+
mark: Mark;
28+
chunkName: string;
29+
fileName: string;
30+
}
2631

2732
export type LazyImport<T> = () => Promise<DefaultImportedComponent<T>>
2833

0 commit comments

Comments
 (0)