UNPKG

6.45 kBJavaScriptView Raw
1const Watcher = require("./utils/watcher");
2const Manifest = require("./manifest");
3const Queue = require("p-queue").default;
4const path = require("path");
5const fs = require("fs");
6const del = require("del");
7const debug = require("debug")("core");
8const mkdirp = require("mkdirp");
9const slash = require("./utils/fixPathSlashes");
10const pkg = require("../package");
11const FileHash = require("./utils/fileHash");
12const setupEnvVariables = require("./utils/setupEnvVars");
13const getBuildInfo = require("./utils/getBuildInfo");
14
15function builder(sourcePath) {
16 const buildStartTime = Date.now();
17
18 // `zero build` is always run in production mode.
19 process.env.ISBUILDER = "true";
20 process.env.NODE_ENV = "production";
21
22 console.log(`\x1b[2m⚡️ Zero ${pkg.version ? `v${pkg.version}` : ""}\x1b[0m`);
23 var bundleInfoMap = {};
24 setupEnvVariables(sourcePath);
25
26 // create the build folder if not present already
27 mkdirp.sync(process.env.BUILDPATH);
28
29 var fileWatch = new Watcher(sourcePath, false);
30 var manifest = new Manifest(sourcePath, fileWatch);
31
32 return new Promise((resolve, reject) => {
33 manifest.on(
34 "change",
35 async ({ manifest, forbiddenFiles, filesUpdated, dependencies }) => {
36 // generate hashes of all files related to page
37 var fileHashes = {};
38 for (var file in manifest.fileToPages) {
39 fileHashes[file] = [
40 await FileHash(file),
41 manifest.fileToPages[file].map(entryFile => {
42 var pageData = manifest.pages.find(page => {
43 return page.entryFile === entryFile;
44 });
45 return pageData.id;
46 })
47 ];
48 }
49
50 var pastFileHashes = false;
51 var pastBuildInfoMap = false;
52 var fileHashPath = path.join(
53 process.env.BUILDPATH,
54 "zero-builds",
55 "_config",
56 "hashes.json"
57 );
58
59 var buildInfoMapPath = path.join(
60 process.env.BUILDPATH,
61 "zero-builds",
62 "build-info.json"
63 );
64
65 try {
66 if (fs.existsSync(fileHashPath) && fs.existsSync(buildInfoMapPath)) {
67 pastBuildInfoMap = require(buildInfoMapPath);
68 pastFileHashes = require(fileHashPath);
69
70 //console.log("using previous zero-builds", pastFileHashes)
71 }
72 } catch (e) {}
73
74 // build paths in a queue with concurrency
75 var queue = new Queue({
76 concurrency: parseInt(process.env.BUILDCONCURRENCY) || 2
77 });
78
79 // see if we can use past zero-build to only build diff
80 var filterPages = false;
81 if (pastFileHashes) {
82 filterPages = {};
83 Object.keys(fileHashes).forEach(file => {
84 if (
85 !pastFileHashes[file] || // a new page that didn't exist before
86 fileHashes[file][0] !== pastFileHashes[file][0] // page changed
87 ) {
88 // mark this page to be dirty
89 manifest.fileToPages[file].forEach(page => {
90 filterPages[page] = true;
91 });
92 }
93 });
94
95 // check if any of the page was removed in new build
96 // page builds that don't exist in new build should be deleted.
97 for (var file in pastFileHashes) {
98 if (!fileHashes[file]) {
99 for (var index in pastFileHashes[file][1]) {
100 try {
101 var pageId = pastFileHashes[file][1][index];
102 debug("deleting", file, pastFileHashes[file][1], pageId);
103 await del(
104 [
105 slash(
106 path.join(
107 process.env.BUILDPATH,
108 "zero-builds",
109 pageId,
110 "/**"
111 )
112 )
113 ],
114 {
115 force: true
116 }
117 );
118 } catch (e) {}
119 }
120 }
121 }
122 }
123
124 for (var i in manifest.pages) {
125 queue.add(
126 async function(index) {
127 var pageData = manifest.pages[index];
128 var pageId = pageData.id;
129 if (
130 filterPages &&
131 !filterPages[pageData.entryFile] &&
132 pastBuildInfoMap[pageId]
133 ) {
134 console.log(
135 `\x1b[2m[${~~index + 1}/${manifest.pages.length}] Skipping`,
136 pageData.path || "/",
137 `\x1b[0m`
138 );
139 bundleInfoMap[pageId] = pastBuildInfoMap[pageId];
140 return;
141 }
142
143 console.log(
144 `[${~~index + 1}/${manifest.pages.length}] Building`,
145 pageData.path || "/"
146 );
147 var { info } = await getBuildInfo(pageData);
148 bundleInfoMap[pageId] = { info }; //the router needs the data at .info of each key
149 }.bind(this, i)
150 );
151 }
152
153 await queue.onIdle();
154 debug("bundleInfo", bundleInfoMap);
155 mkdirp.sync(path.join(process.env.BUILDPATH, "zero-builds"));
156 fs.writeFileSync(
157 path.join(process.env.BUILDPATH, "zero-builds", "build-info.json"),
158 JSON.stringify(bundleInfoMap),
159 "utf8"
160 );
161
162 // copy package.json
163 mkdirp.sync(path.join(process.env.BUILDPATH, "zero-builds", "_config"));
164
165 fs.writeFileSync(
166 path.join(
167 process.env.BUILDPATH,
168 "zero-builds",
169 "_config",
170 "package.json"
171 ),
172 fs.readFileSync(path.join(process.env.SOURCEPATH, "package.json"))
173 );
174
175 // copy .babelrc
176 fs.writeFileSync(
177 path.join(
178 process.env.BUILDPATH,
179 "zero-builds",
180 "_config",
181 ".babelrc"
182 ),
183 fs.readFileSync(path.join(process.env.SOURCEPATH, ".babelrc"))
184 );
185
186 // save a file hash map
187 fs.writeFileSync(fileHashPath, JSON.stringify(fileHashes));
188
189 console.log(
190 `\x1b[2mBuilt in ${((Date.now() - buildStartTime) / 1000).toFixed(
191 1
192 )} seconds.\x1b[0m`
193 );
194
195 // resolve with manifest
196 resolve({ manifest, forbiddenFiles, dependencies });
197 }
198 );
199 });
200}
201
202module.exports = builder;
203
\No newline at end of file