-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(build): add node build file (#54)
* feat(build): add node build file * fix(build): add whitespace between source files in combined * fix(build): get closure compiler step working! * fix(build): fix shebang * fix(build): remove `package-lock.json`
- Loading branch information
1 parent
4b3073e
commit 8df371d
Showing
3 changed files
with
211 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
#!/usr/bin/env node | ||
|
||
const start = performance.now(); | ||
|
||
const fs = require("node:fs"); | ||
const child_process = require("node:child_process"); | ||
const { Build } = require("./buildClass"); | ||
|
||
const BUILD_DIR = "build"; | ||
const ENGINE_NAME = "littlejs"; | ||
|
||
// Nuke build dir and recreate | ||
fs.rmSync(BUILD_DIR, { recursive: true, force: true }); | ||
fs.mkdirSync(BUILD_DIR); | ||
|
||
const closureCompilerStep = (filename) => { | ||
fs.copyFileSync(filename, `${filename}.tmp`); | ||
try { | ||
child_process.execSync( | ||
`npx google-closure-compiler --js=${filename}.tmp --js_output_file=${filename} --language_out=ECMASCRIPT_2021 --warning_level=VERBOSE --jscomp_off="*"` | ||
); | ||
} catch (e) { | ||
console.error(e); | ||
console.error( | ||
"Failed to run Google Closure Compiler step... Make sure the file is valid before running?" | ||
); | ||
process.exit(1); | ||
} | ||
fs.rmSync(`${filename}.tmp`); | ||
}; | ||
|
||
const uglifyBuildStep = (filename) => { | ||
try { | ||
child_process.execSync(`npx uglifyjs -o ${filename} -- ${filename}`); | ||
} catch (e) { | ||
console.error(e); | ||
process.exit(1); | ||
} | ||
}; | ||
|
||
// Build engine -- all | ||
{ | ||
const build = new Build(); | ||
build | ||
.addSourceFile("src/engineDebug.js") | ||
.addSourceFile("src/engineUtilities.js") | ||
.addSourceFile("src/engineSettings.js") | ||
.addSourceFile("src/engineObject.js") | ||
.addSourceFile("src/engineDraw.js") | ||
.addSourceFile("src/engineInput.js") | ||
.addSourceFile("src/engineAudio.js") | ||
.addSourceFile("src/engineTileLayer.js") | ||
.addSourceFile("src/engineParticles.js") | ||
.addSourceFile("src/engineMedals.js") | ||
.addSourceFile("src/engineWebGL.js") | ||
.addSourceFile("src/engine.js") | ||
.setOutputFile(`build/${ENGINE_NAME}.js`) | ||
.build(); | ||
} | ||
|
||
// Build engine -- release | ||
{ | ||
const build = new Build(); | ||
build | ||
.addSourceFile("src/engineRelease.js") | ||
.addSourceFile("src/engineUtilities.js") | ||
.addSourceFile("src/engineSettings.js") | ||
.addSourceFile("src/engine.js") | ||
.addSourceFile("src/engineObject.js") | ||
.addSourceFile("src/engineDraw.js") | ||
.addSourceFile("src/engineInput.js") | ||
.addSourceFile("src/engineAudio.js") | ||
.addSourceFile("src/engineTileLayer.js") | ||
.addSourceFile("src/engineParticles.js") | ||
.addSourceFile("src/engineMedals.js") | ||
.addSourceFile("src/engineWebGL.js") | ||
.setOutputFile(`build/${ENGINE_NAME}.release.js`) | ||
.build(); | ||
} | ||
|
||
// Build engine -- minified | ||
{ | ||
const build = new Build(); | ||
build | ||
.addSourceFile(`build/${ENGINE_NAME}.release.js`) | ||
.setOutputFile(`build/${ENGINE_NAME}.min.js`) | ||
.addBuildStep(closureCompilerStep) | ||
.addBuildStep(uglifyBuildStep) | ||
.build(); | ||
} | ||
|
||
// Build engine -- ESM | ||
{ | ||
const build = new Build(); | ||
build | ||
.addSourceFile(`build/${ENGINE_NAME}.js`) | ||
.addSourceFile("src/engineExport.js") | ||
.setOutputFile(`build/${ENGINE_NAME}.esm.js`) | ||
.build(); | ||
} | ||
|
||
// Build engine -- ESM minified / release | ||
{ | ||
const build = new Build(); | ||
build | ||
.addSourceFile(`build/${ENGINE_NAME}.min.js`) | ||
.addSourceFile("src/engineExport.js") | ||
.setOutputFile(`build/${ENGINE_NAME}.esm.min.js`) | ||
.addBuildStep(uglifyBuildStep) | ||
.build(); | ||
} | ||
|
||
// Run tsc to create type definitions | ||
try { | ||
child_process.execSync( | ||
`npx tsc build/${ENGINE_NAME}.esm.js --declaration --allowJs --emitDeclarationOnly --outFile build/${ENGINE_NAME}.d.ts` | ||
); | ||
} catch (e) { | ||
console.error(e); | ||
process.exit(1); | ||
} | ||
|
||
const end = performance.now(); | ||
const duration = end - start; | ||
|
||
console.log(`Build completed in ${duration.toFixed(2)} ms.`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
const fs = require("node:fs"); | ||
|
||
/** | ||
A class representing a single build with its own source files, build steps, and output file | ||
*/ | ||
class Build { | ||
#files; | ||
#outputFile; | ||
#buildSteps; | ||
|
||
constructor() { | ||
this.#files = []; | ||
this.#outputFile = "out.js"; | ||
this.#buildSteps = []; | ||
} | ||
|
||
addSourceFile(filename) { | ||
this.#files.push(filename); | ||
return this; | ||
} | ||
|
||
setOutputFile(filename) { | ||
this.#outputFile = filename; | ||
return this; | ||
} | ||
|
||
/** | ||
* | ||
* @param {buildStepCallback} cb - A callback that accepts a `filename` as its only argument representing the file to execute this step on. | ||
* @returns {this} | ||
*/ | ||
addBuildStep(cb) { | ||
this.#buildSteps.push(cb); | ||
return this; | ||
} | ||
|
||
/** | ||
* @returns {boolean} Whether build completed successfully or not. | ||
*/ | ||
build() { | ||
// read files | ||
const files = this.#files; | ||
if (!files.length) { | ||
console.error( | ||
"No files given to build. Make sure you add files with `addSourceFile` before building." | ||
); | ||
return false; // no files, this should be an error | ||
} | ||
|
||
// concat files into one buffer | ||
let buf = fs.readFileSync(files[0]); | ||
buf += "\n"; | ||
// Start with i = 1 since we init buffer with 0th index | ||
for (let i = 1; i < files.length; i += 1) { | ||
buf += fs.readFileSync(files[i]); | ||
buf += "\n"; | ||
} | ||
|
||
// output file | ||
fs.writeFileSync(this.#outputFile, buf, { flag: "w+" }); | ||
|
||
// go through build steps in order | ||
const buildSteps = this.#buildSteps; | ||
for (let i = 0; i < buildSteps.length; i += 1) { | ||
buildSteps[i](this.#outputFile); | ||
} | ||
} | ||
|
||
get sourceFiles() { | ||
return this.#files; | ||
} | ||
|
||
get outputFile() { | ||
return this.#outputFile; | ||
} | ||
} | ||
|
||
/** | ||
* Callback provided to run a build step in the Build class. | ||
* @callback buildStepCallback | ||
* @param {string} filename | ||
*/ | ||
|
||
module.exports = { Build }; |