@@ -4,6 +4,7 @@ const axios = require('axios');
4
4
const client = axios . default ;
5
5
const fs = require ( 'fs' ) ;
6
6
const path = require ( 'path' ) ;
7
+ const download = require ( 'download' ) ;
7
8
8
9
const buildDir = path . join ( __dirname , '../build/' ) ;
9
10
@@ -13,6 +14,9 @@ const assetHistoryDir = path.join(buildDir, 'asset-history.json');
13
14
const readFileAsync = promisify ( fs . readFile ) ;
14
15
const writeFileAsync = promisify ( fs . writeFile ) ;
15
16
17
+ /**
18
+ * Loads current asset-history from CDN
19
+ */
16
20
async function getAssetHistory ( ) {
17
21
try {
18
22
const response = await client . get (
@@ -26,16 +30,27 @@ async function getAssetHistory() {
26
30
}
27
31
}
28
32
33
+ /**
34
+ * reads asset-manifest.json of current build
35
+ */
29
36
async function readAssetManifest ( ) {
30
37
const data = await readFileAsync ( assetManifestDir , 'utf-8' ) ;
31
38
return JSON . parse ( data ) ;
32
39
}
33
40
41
+ /**
42
+ * Saves asset-history.json with given data
43
+ * @param data
44
+ */
34
45
async function writeAssetHistory ( data ) {
35
46
const stringified = JSON . stringify ( data , null , 2 ) ;
36
47
return writeFileAsync ( assetHistoryDir , stringified , 'utf-8' ) ;
37
48
}
38
49
50
+ /**
51
+ * Filters out files that end with .map
52
+ * @param {string[] } files
53
+ */
39
54
function filterOutMapFiles ( files ) {
40
55
return Object . fromEntries (
41
56
Object . entries ( files ) . filter (
@@ -44,12 +59,44 @@ function filterOutMapFiles(files) {
44
59
) ;
45
60
}
46
61
62
+ /**
63
+ * Downloads file at the corresponding path
64
+ * @param {string[] } urls
65
+ */
66
+ function downloadUrls ( urls ) {
67
+ return Promise . all (
68
+ urls . map ( url => {
69
+ const downloadPath = url
70
+ . slice ( 0 , url . lastIndexOf ( '/' ) )
71
+ . replace ( 'https://static.velog.io' , '' ) ;
72
+
73
+ return download ( url , path . join ( buildDir , downloadPath ) ) ;
74
+ } ) ,
75
+ ) ;
76
+ }
77
+
47
78
async function keepChunks ( ) {
48
79
const assetHistory = await getAssetHistory ( ) ;
49
80
const assetManifest = await readAssetManifest ( ) ;
50
81
51
- // TODO: filter out old data
52
- // TODO: download if exists...
82
+ // filter out old data (always keep the latest one)
83
+ const cacheDuration = 1000 * 60 * 60 * 24 * 3 ;
84
+ const filteredHistory = assetHistory . history . filter (
85
+ ( item , index , array ) =>
86
+ index === array . length - 1 || Date . now ( ) - item . date < cacheDuration ,
87
+ ) ;
88
+
89
+ const urls = filteredHistory
90
+ . reduce ( ( acc , current ) => {
91
+ return acc . concat ( Object . values ( current . files ) ) ;
92
+ } , [ ] )
93
+ . filter ( url =>
94
+ [ 'index.html' , 'loadable-stats.json' , 'service-worker.js' ] . every (
95
+ ignored => ! url . includes ( ignored ) ,
96
+ ) ,
97
+ ) ;
98
+
99
+ await downloadUrls ( urls ) ;
53
100
54
101
// update assetHistory
55
102
assetHistory . history . push ( {
@@ -61,35 +108,3 @@ async function keepChunks() {
61
108
}
62
109
63
110
keepChunks ( ) ;
64
-
65
- // const assetHistory = {
66
- // history: [
67
- // {
68
- // date: '2020-01-17T14:30:00.251Z',
69
- // files: {
70
- // 'static/js/0.98b2d894.chunk.js':
71
- // 'https://static.velog.io/static/js/0.98b2d894.chunk.js',
72
- // 'static/js/0.98b2d894.chunk.js.map':
73
- // 'https://static.velog.io/static/js/0.98b2d894.chunk.js.map',
74
- // },
75
- // },
76
- // {
77
- // date: '2020-01-17T14:30:00.251Z',
78
- // files: {
79
- // 'static/js/0.98b2d894.chunk.js':
80
- // 'https://static.velog.io/static/js/0.98b2d894.chunk.js',
81
- // 'static/js/0.98b2d894.chunk.js.map':
82
- // 'https://static.velog.io/static/js/0.98b2d894.chunk.js.map',
83
- // },
84
- // },
85
- // ],
86
- // };
87
-
88
- // https://static.velog.io/manifest-history.json을 다운로드 (axios로 요청하는것 만으로도 충분)
89
- // 3일 이상된 객체들을 filter out
90
- // 남아있는 것들 모두 다운로드를 하고
91
- // 현재 asset-manifest 열어서
92
- // files의 .map으로 끝나는 것들 filter out 한다음에
93
- // 배열에 push
94
-
95
- // 이걸 manifest-history.json으로 build 디렉터리에 저장
0 commit comments