1 Star 0 Fork 5

微小的光/cesium

forked from Gitee 极速下载/cesium 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
server.js 15.46 KB
一键复制 编辑 原始数据 按行查看 历史
Gabby Getz 提交于 2022-12-15 13:57 . Fix file watcher for workers
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
/*eslint-env node*/
import fs from "fs";
import path from "path";
import { performance } from "perf_hooks";
import request from "request";
import { URL } from "url";
import chokidar from "chokidar";
import compression from "compression";
import express from "express";
import yargs from "yargs";
const argv = yargs(process.argv)
.options({
port: {
default: 8080,
description: "Port to listen on.",
},
public: {
type: "boolean",
description: "Run a public server that listens on all interfaces.",
},
"upstream-proxy": {
description:
'A standard proxy server that will be used to retrieve data. Specify a URL including port, e.g. "http://proxy:8000".',
},
"bypass-upstream-proxy-hosts": {
description:
'A comma separated list of hosts that will bypass the specified upstream_proxy, e.g. "lanhost1,lanhost2"',
},
production: {
type: "boolean",
description: "If true, skip build step and serve existing built files.",
},
})
.help().argv;
import {
bundleWorkers,
createCesiumJs,
createJsHintOptions,
createCombinedSpecList,
glslToJavaScript,
buildEngine,
buildWidgets,
buildCesium,
} from "./build.js";
const sourceFiles = [
"packages/engine/Source/**/*.js",
"!packages/engine/Source/*.js",
"packages/widgets/Source/**/*.js",
"!packages/widgets/Source/*.js",
"!packages/engine/Source/Shaders/**",
"!packages/engine/Source/Workers/**",
"!packages/engine/Source/WorkersES6/**",
"packages/engine/Source/WorkersES6/createTaskProcessorWorker.js",
"!packages/engine/Source/ThirdParty/Workers/**",
"!packages/engine/Source/ThirdParty/google-earth-dbroot-parser.js",
"!packages/engine/Source/ThirdParty/_*",
];
const specFiles = [
"packages/engine/Specs/**/*Spec.js",
"!packages/engine/Specs/SpecList.js",
"packages/widgets/Specs/**/*Spec.js",
"!packages/widgets/Specs/SpecList.js",
"Specs/*.js",
"!Specs/SpecList.js",
"Specs/TestWorkers/*.js",
];
const shaderFiles = ["packages/engine/Source/Shaders/**/*.glsl"];
const workerSourceFiles = ["packages/engine/Source/WorkersES6/*.js"];
const outputDirectory = path.join("Build", "CesiumDev");
function formatTimeSinceInSeconds(start) {
return Math.ceil((performance.now() - start) / 100) / 10;
}
/**
* Returns CesiumJS bundles configured for development.
*
* @returns {Bundles} The bundles.
*/
async function generateDevelopmentBuild() {
const startTime = performance.now();
// Build @cesium/engine
console.log("[1/3] Building @cesium/engine...");
await buildEngine({
sourcemap: true,
incremental: true,
write: false,
minify: false,
});
// Build @cesium/widgets
console.log("[2/3] Building @cesium/widgets...");
await buildWidgets({
sourcemap: true,
incremental: true,
write: false,
minify: false,
});
// Build CesiumJS
console.log("[3/3] Building CesiumJS...");
const bundles = await buildCesium({
development: true,
iife: true,
incremental: true,
minify: false,
node: false,
outputDirectory: outputDirectory,
removePragmas: false,
sourcemap: true,
write: false,
});
console.log(
`Cesium built in ${formatTimeSinceInSeconds(startTime)} seconds.`
);
return {
esmResult: bundles.esmBundle,
iifeResult: bundles.iifeBundle,
specResult: bundles.specsBundle,
};
}
const serveResult = (result, fileName, res, next) => {
let bundle;
for (const out of result.outputFiles) {
if (path.basename(out.path) === fileName) {
bundle = out.text;
}
}
if (!bundle) {
next(new Error("Failed to generate bundle"));
return;
}
res.append("Cache-Control", "max-age=0");
res.append("Content-Type", "application/javascript");
res.send(bundle);
};
(async function () {
const gzipHeader = Buffer.from("1F8B08", "hex");
let esmResult, iifeResult, specResult;
const production = argv.production;
if (!production) {
const bundles = await generateDevelopmentBuild();
esmResult = bundles.esmResult;
iifeResult = bundles.iifeResult;
specResult = bundles.specResult;
}
// eventually this mime type configuration will need to change
// https://github.com/visionmedia/send/commit/d2cb54658ce65948b0ed6e5fb5de69d022bef941
// *NOTE* Any changes you make here must be mirrored in web.config.
const mime = express.static.mime;
mime.define(
{
"application/json": ["czml", "json", "geojson", "topojson"],
"application/wasm": ["wasm"],
"image/ktx2": ["ktx2"],
"model/gltf+json": ["gltf"],
"model/gltf-binary": ["bgltf", "glb"],
"application/octet-stream": [
"b3dm",
"pnts",
"i3dm",
"cmpt",
"geom",
"vctr",
],
"text/plain": ["glsl"],
},
true
);
const app = express();
app.use(compression());
//eslint-disable-next-line no-unused-vars
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
function checkGzipAndNext(req, res, next) {
const baseURL = `${req.protocol}://${req.headers.host}/`;
const reqUrl = new URL(req.url, baseURL);
const filePath = reqUrl.pathname.substring(1);
const readStream = fs.createReadStream(filePath, { start: 0, end: 2 });
//eslint-disable-next-line no-unused-vars
readStream.on("error", function (err) {
next();
});
readStream.on("data", function (chunk) {
if (chunk.equals(gzipHeader)) {
res.header("Content-Encoding", "gzip");
}
next();
});
}
const knownTilesetFormats = [
/\.b3dm/,
/\.pnts/,
/\.i3dm/,
/\.cmpt/,
/\.glb/,
/\.geom/,
/\.vctr/,
/tileset.*\.json$/,
];
app.get(knownTilesetFormats, checkGzipAndNext);
if (!production) {
// Set up file watcher for more expensive operations which would block during
// "just in time" compilation
const workerWatcher = chokidar.watch(workerSourceFiles, {
ignoreInitial: true,
});
workerWatcher.on("all", async () => {
try {
const start = performance.now();
await bundleWorkers({
input: ["packages/engine/Source/Workers/**"],
inputES6: workerSourceFiles,
path: outputDirectory,
sourcemap: true,
});
console.log(
`Rebuilt Workers/* in ${formatTimeSinceInSeconds(start)} seconds.`
);
} catch (e) {
console.error(e);
}
});
app.get("/Build/CesiumUnminified/Cesium.js", async function (
//eslint-disable-next-line no-unused-vars
req,
res,
next
) {
if (!iifeResult?.outputFiles || iifeResult.outputFiles.length === 0) {
try {
const start = performance.now();
await createCesiumJs();
iifeResult = await iifeResult.rebuild();
console.log(
`Rebuilt Cesium.js in ${formatTimeSinceInSeconds(start)} seconds.`
);
} catch (e) {
next(e);
}
}
return serveResult(iifeResult, "Cesium.js", res, next);
});
app.get("/Build/CesiumUnminified/Cesium.js.map", async function (
//eslint-disable-next-line no-unused-vars
req,
res,
next
) {
if (!iifeResult?.outputFiles || iifeResult.outputFiles.length === 0) {
try {
const start = performance.now();
await createCesiumJs();
iifeResult = await iifeResult.rebuild();
console.log(
`Rebuilt Cesium.js in ${formatTimeSinceInSeconds(start)} seconds.`
);
} catch (e) {
next(e);
}
}
return serveResult(iifeResult, "Cesium.js.map", res, next);
});
app.get("/Build/CesiumUnminified/index.js", async function (
//eslint-disable-next-line no-unused-vars
req,
res,
next
) {
if (!esmResult?.outputFiles || esmResult.outputFiles.length === 0) {
try {
const start = performance.now();
await createCesiumJs();
esmResult = await esmResult.rebuild();
console.log(
`Rebuilt index.js in ${formatTimeSinceInSeconds(start)} seconds.`
);
} catch (e) {
next(e);
}
}
return serveResult(esmResult, "index.js", res, next);
});
app.get("/Build/CesiumUnminified/index.js.map", async function (
//eslint-disable-next-line no-unused-vars
req,
res,
next
) {
if (!esmResult?.outputFiles || esmResult.outputFiles.length === 0) {
try {
const start = performance.now();
await createCesiumJs();
esmResult = await esmResult.rebuild();
console.log(
`Rebuilt index.js in ${formatTimeSinceInSeconds(start)} seconds.`
);
} catch (e) {
next(e);
}
}
return serveResult(esmResult, "index.js.map", res, next);
});
const glslWatcher = chokidar.watch(shaderFiles, { ignoreInitial: true });
glslWatcher.on("all", async () => {
await glslToJavaScript(false, "Build/minifyShaders.state", "engine");
esmResult.outputFiles = [];
iifeResult.outputFiles = [];
});
let jsHintOptionsCache;
const sourceCodeWatcher = chokidar.watch(sourceFiles, {
ignoreInitial: true,
});
sourceCodeWatcher.on("all", () => {
esmResult.outputFiles = [];
iifeResult.outputFiles = [];
jsHintOptionsCache = undefined;
});
app.get("/Apps/Sandcastle/jsHintOptions.js", async function (
//eslint-disable-next-line no-unused-vars
req,
res,
//eslint-disable-next-line no-unused-vars
next
) {
if (!jsHintOptionsCache) {
jsHintOptionsCache = await createJsHintOptions();
}
res.append("Cache-Control", "max-age=0");
res.append("Content-Type", "application/javascript");
res.send(jsHintOptionsCache);
});
let specRebuildPromise = Promise.resolve();
//eslint-disable-next-line no-unused-vars
app.get("/Build/Specs/*", async function (req, res, next) {
// Multiple files may be requested at this path, calling this function in quick succession.
// Await the previous build before re-building again.
await specRebuildPromise;
if (!specResult?.outputFiles || specResult.outputFiles.length === 0) {
try {
const start = performance.now();
specRebuildPromise = specResult.rebuild();
specResult = await specRebuildPromise;
console.log(
`Rebuilt Specs/* in ${formatTimeSinceInSeconds(start)} seconds.`
);
} catch (e) {
next(e);
}
}
return serveResult(specResult, path.basename(req.originalUrl), res, next);
});
const specWatcher = chokidar.watch(specFiles, { ignoreInitial: true });
specWatcher.on("all", async (event) => {
if (event === "add" || event === "unlink") {
await createCombinedSpecList();
}
specResult.outputFiles = [];
});
// Serve any static files starting with "Build/CesiumUnminified" from the
// development build instead. That way, previous build output is preserved
// while the latest is being served
app.use("/Build/CesiumUnminified", express.static("Build/CesiumDev"));
}
app.use(express.static(path.resolve(".")));
function getRemoteUrlFromParam(req) {
let remoteUrl = req.params[0];
if (remoteUrl) {
// add http:// to the URL if no protocol is present
if (!/^https?:\/\//.test(remoteUrl)) {
remoteUrl = `http://${remoteUrl}`;
}
remoteUrl = new URL(remoteUrl);
// copy query string
const baseURL = `${req.protocol}://${req.headers.host}/`;
remoteUrl.search = new URL(req.url, baseURL).search;
}
return remoteUrl;
}
const dontProxyHeaderRegex = /^(?:Host|Proxy-Connection|Connection|Keep-Alive|Transfer-Encoding|TE|Trailer|Proxy-Authorization|Proxy-Authenticate|Upgrade)$/i;
//eslint-disable-next-line no-unused-vars
function filterHeaders(req, headers) {
const result = {};
// filter out headers that are listed in the regex above
Object.keys(headers).forEach(function (name) {
if (!dontProxyHeaderRegex.test(name)) {
result[name] = headers[name];
}
});
return result;
}
const upstreamProxy = argv["upstream-proxy"];
const bypassUpstreamProxyHosts = {};
if (argv["bypass-upstream-proxy-hosts"]) {
argv["bypass-upstream-proxy-hosts"].split(",").forEach(function (host) {
bypassUpstreamProxyHosts[host.toLowerCase()] = true;
});
}
//eslint-disable-next-line no-unused-vars
app.get("/proxy/*", function (req, res, next) {
// look for request like http://localhost:8080/proxy/http://example.com/file?query=1
let remoteUrl = getRemoteUrlFromParam(req);
if (!remoteUrl) {
// look for request like http://localhost:8080/proxy/?http%3A%2F%2Fexample.com%2Ffile%3Fquery%3D1
remoteUrl = Object.keys(req.query)[0];
if (remoteUrl) {
const baseURL = `${req.protocol}://${req.headers.host}/`;
remoteUrl = new URL(remoteUrl, baseURL);
}
}
if (!remoteUrl) {
return res.status(400).send("No url specified.");
}
if (!remoteUrl.protocol) {
remoteUrl.protocol = "http:";
}
let proxy;
if (upstreamProxy && !(remoteUrl.host in bypassUpstreamProxyHosts)) {
proxy = upstreamProxy;
}
// encoding : null means "body" passed to the callback will be raw bytes
request.get(
{
url: remoteUrl.toString(),
headers: filterHeaders(req, req.headers),
encoding: null,
proxy: proxy,
},
//eslint-disable-next-line no-unused-vars
function (error, response, body) {
let code = 500;
if (response) {
code = response.statusCode;
res.header(filterHeaders(req, response.headers));
}
res.status(code).send(body);
}
);
});
const server = app.listen(
argv.port,
argv.public ? undefined : "localhost",
function () {
if (argv.public) {
console.log(
"Cesium development server running publicly. Connect to http://localhost:%d/",
server.address().port
);
} else {
console.log(
"Cesium development server running locally. Connect to http://localhost:%d/",
server.address().port
);
}
}
);
server.on("error", function (e) {
if (e.code === "EADDRINUSE") {
console.log(
"Error: Port %d is already in use, select a different port.",
argv.port
);
console.log("Example: node server.js --port %d", argv.port + 1);
} else if (e.code === "EACCES") {
console.log(
"Error: This process does not have permission to listen on port %d.",
argv.port
);
if (argv.port < 1024) {
console.log("Try a port number higher than 1024.");
}
}
console.log(e);
process.exit(1);
});
server.on("close", function () {
console.log("Cesium development server stopped.");
});
let isFirstSig = true;
process.on("SIGINT", function () {
if (isFirstSig) {
console.log("Cesium development server shutting down.");
server.close(function () {
process.exit(0);
});
if (!production) {
esmResult.rebuild.dispose();
iifeResult.rebuild.dispose();
specResult.rebuild.dispose();
}
isFirstSig = false;
} else {
console.log("Cesium development server force kill.");
process.exit(1);
}
});
})();
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jnzqwd/cesium.git
git@gitee.com:jnzqwd/cesium.git
jnzqwd
cesium
cesium
main

搜索帮助