Building app vs editing actual files

Hi!

This is probably a stupid question and is general to app dev and not just Meteor.

Why build apps which can take minutes to link,compile, archive, etc…for deploying when you can just edit actual code files i.e the minified app.js.

Besides the obvious reason of losing track of changes, etc…

Try to fix a bug reading this file

import assert from 'assert';import{readFileSync,chmodSync}from "fs";import{createServer}from 'http';import{userInfo}from "os";import{join as pathJoin,dirname as pathDirname}from 'path';import{parse as parseUrl}from 'url';import{createHash}from 'crypto';import{connect}from './connect.js';import compress from 'compression';import cookieParser from 'cookie-parser';import qs from 'qs';import parseRequest from 'parseurl';import basicAuth from 'basic-auth-connect';import{lookup as lookupUserAgent}from 'useragent';import{isModern}from 'meteor/modern-browsers';import send from 'send';import{removeExistingSocketFile,registerSocketFileCleanup}from './socket_file.js';import cluster from "cluster";import whomst from "@vlasky/whomst";import streamToString from 'stream-to-string';import to from 'await-to-js';import html2amp from 'html2amp';var SHORT_SOCKET_TIMEOUT=5*1000;var LONG_SOCKET_TIMEOUT=120*1000;export const WebApp={};export const WebAppInternals={};const hasOwn=Object.prototype.hasOwnProperty;connect.basicAuth=basicAuth;WebAppInternals.NpmModules={connect:{version:Npm.require('connect/package.json').version,module:connect}};WebApp.defaultArch='web.browser.legacy';WebApp.clientPrograms={};var archPath={};var bundledJsCssUrlRewriteHook=function(url){var bundledPrefix=__meteor_runtime_config__.ROOT_URL_PATH_PREFIX||'';return bundledPrefix+url};var sha1=function(contents){var hash=createHash('sha1');hash.update(contents);return hash.digest('hex')};function shouldCompress(req,res){if(req.headers['x-no-compression']){return!1}
return compress.filter(req,res)}
var camelCase=function(name){var parts=name.split(' ');parts[0]=parts[0].toLowerCase();for(var i=1;i<parts.length;++i){parts[i]=parts[i].charAt(0).toUpperCase()+parts[i].substr(1)}
return parts.join('')};var identifyBrowser=function(userAgentString){var userAgent=lookupUserAgent(userAgentString);return{name:camelCase(userAgent.family),major:+userAgent.major,minor:+userAgent.minor,patch:+userAgent.patch}};WebAppInternals.identifyBrowser=identifyBrowser;WebApp.categorizeRequest=function(req){if(req.browser&&req.arch&&typeof req.modern==='boolean'){return req}
const browser=identifyBrowser(req.headers['user-agent']);const modern=isModern(browser);const path=typeof req.pathname==='string'?req.pathname:parseRequest(req).pathname;const categorized={browser,modern,path,arch:WebApp.defaultArch,url:parseUrl(req.url,!0),dynamicHead:req.dynamicHead,dynamicBody:req.dynamicBody,headers:req.headers,cookies:req.cookies};const pathParts=path.split('/');const archKey=pathParts[1];if(archKey.startsWith('__')){const archCleaned='web.'+archKey.slice(2);if(hasOwn.call(WebApp.clientPrograms,archCleaned)){pathParts.splice(1,1);return Object.assign(categorized,{arch:archCleaned,path:pathParts.join('/')})}}
const preferredArchOrder=isModern(browser)?['web.browser','web.browser.legacy']:['web.browser.legacy','web.browser'];for(const arch of preferredArchOrder){if(hasOwn.call(WebApp.clientPrograms,arch)){return Object.assign(categorized,{arch})}}
return categorized};var htmlAttributeHooks=[];var getHtmlAttributes=function(request){var combinedAttributes={};_.each(htmlAttributeHooks||[],function(hook){var attributes=hook(request);if(attributes===null)return;if(typeof attributes!=='object')
throw Error('HTML attribute hook must return null or object');_.extend(combinedAttributes,attributes)});return combinedAttributes};WebApp.addHtmlAttributeHook=function(hook){htmlAttributeHooks.push(hook)};var appUrl=function(url){if(url==='/favicon.ico'||url==='/robots.txt')return!1;if(url==='/app.manifest')return!1;if(RoutePolicy.classify(url))return!1;return!0};Meteor.startup(function(){function getter(key){return function(arch){arch=arch||WebApp.defaultArch;const program=WebApp.clientPrograms[arch];const value=program&&program[key];return typeof value==='function'?(program[key]=value()):value}}
WebApp.calculateClientHash=WebApp.clientHash=getter('version');WebApp.calculateClientHashRefreshable=getter('versionRefreshable');WebApp.calculateClientHashNonRefreshable=getter('versionNonRefreshable');WebApp.calculateClientHashReplaceable=getter('versionReplaceable');WebApp.getRefreshableAssets=getter('refreshableAssets')});WebApp._timeoutAdjustmentRequestCallback=function(req,res){req.setTimeout(LONG_SOCKET_TIMEOUT);var finishListeners=res.listeners('finish');res.removeAllListeners('finish');res.on('finish',function(){res.setTimeout(SHORT_SOCKET_TIMEOUT)});_.each(finishListeners,function(l){res.on('finish',l)})};var boilerplateByArch={};const boilerplateDataCallbacks=Object.create(null);WebAppInternals.registerBoilerplateDataCallback=function(key,callback){const previousCallback=boilerplateDataCallbacks[key];if(typeof callback==='function'){boilerplateDataCallbacks[key]=callback}else{assert.strictEqual(callback,null);delete boilerplateDataCallbacks[key]}
return previousCallback||null};function getBoilerplate(request,arch){return getBoilerplateAsync(request,arch).await()}
function getBoilerplateAsync(request,arch){const boilerplate=boilerplateByArch[arch];const data=Object.assign({},boilerplate.baseData,{htmlAttributes:getHtmlAttributes(request)},_.pick(request,'dynamicHead','dynamicBody'));let madeChanges=!1;let promise=Promise.resolve();Object.keys(boilerplateDataCallbacks).forEach(key=>{promise=promise.then(()=>{const callback=boilerplateDataCallbacks[key];return callback(request,data,arch)}).then(result=>{if(result!==!1){madeChanges=!0}})});return promise.then(()=>({stream:boilerplate.toHTMLStream(data),statusCode:data.statusCode,headers:data.headers}))}
WebAppInternals.generateBoilerplateInstance=function(arch,manifest,additionalOptions){additionalOptions=additionalOptions||{};const meteorRuntimeConfig=JSON.stringify(encodeURIComponent(JSON.stringify({...__meteor_runtime_config__,...(additionalOptions.runtimeConfigOverrides||{})})));return new Boilerplate(arch,manifest,_.extend({pathMapper(itemPath){return pathJoin(archPath[arch],itemPath)},baseDataExtension:{additionalStaticJs:_.map(additionalStaticJs||[],function(contents,pathname){return{pathname:pathname,contents:contents}}),meteorRuntimeConfig,meteorRuntimeHash:sha1(meteorRuntimeConfig),rootUrlPathPrefix:__meteor_runtime_config__.ROOT_URL_PATH_PREFIX||'',bundledJsCssUrlRewriteHook:bundledJsCssUrlRewriteHook,sriMode:sriMode,inlineScriptsAllowed:WebAppInternals.inlineScriptsAllowed(),inline:additionalOptions.inline}},additionalOptions))};WebAppInternals.staticFilesMiddleware=async function(staticFilesByArch,req,res,next){var pathname=parseRequest(req).pathname;try{pathname=decodeURIComponent(pathname)}catch(e){next();return}
var serveStaticJs=function(s){if(req.method==='GET'||req.method==='HEAD'){res.writeHead(200,{'Content-type':'application/javascript; charset=UTF-8','Content-Length':Buffer.byteLength(s),});res.write(s);res.end()}else{const status=req.method==='OPTIONS'?200:405;res.writeHead(status,{'Allow':'OPTIONS, GET, HEAD','Content-Length':'0',});res.end()}};if(_.has(additionalStaticJs,pathname)&&!WebAppInternals.inlineScriptsAllowed()){serveStaticJs(additionalStaticJs[pathname]);return}
const{arch,path}=WebApp.categorizeRequest(req);if(!hasOwn.call(WebApp.clientPrograms,arch)){next();return}
const program=WebApp.clientPrograms[arch];await program.paused;if(path==='/meteor_runtime_config.js'&&!WebAppInternals.inlineScriptsAllowed()){serveStaticJs(`__meteor_runtime_config__ = ${program.meteorRuntimeConfig};`);return}
const info=getStaticFileInfo(staticFilesByArch,pathname,path,arch);if(!info){next();return}
if(req.method!=='HEAD'&&req.method!=='GET'){const status=req.method==='OPTIONS'?200:405;res.writeHead(status,{'Allow':'OPTIONS, GET, HEAD','Content-Length':'0',})
res.end();return}
const maxAge=info.cacheable?1000*60*60*24*365:0;if(info.cacheable){res.setHeader('Vary','User-Agent')}
if(info.sourceMapUrl){res.setHeader('X-SourceMap',__meteor_runtime_config__.ROOT_URL_PATH_PREFIX+info.sourceMapUrl)}
if(info.type==='js'||info.type==='dynamic js'){res.setHeader('Content-Type','application/javascript; charset=UTF-8')}else if(info.type==='css'){res.setHeader('Content-Type','text/css; charset=UTF-8')}else if(info.type==='json'){res.setHeader('Content-Type','application/json; charset=UTF-8')}
if(info.hash){res.setHeader('ETag','"'+info.hash+'"')}
if(info.content){res.setHeader('Content-Length',Buffer.byteLength(info.content));res.write(info.content);res.end()}else{send(req,info.absolutePath,{maxage:maxAge,dotfiles:'allow',lastModified:!1}).on('error',function(err){Log.error('Error serving static file '+err);res.writeHead(500);res.end()}).on('directory',function(){Log.error('Unexpected directory '+info.absolutePath);res.writeHead(500);res.end()}).pipe(res)}};function getStaticFileInfo(staticFilesByArch,originalPath,path,arch){if(!hasOwn.call(WebApp.clientPrograms,arch)){return null}
const staticArchList=Object.keys(staticFilesByArch);const archIndex=staticArchList.indexOf(arch);if(archIndex>0){staticArchList.unshift(staticArchList.splice(archIndex,1)[0])}
let info=null;staticArchList.some(arch=>{const staticFiles=staticFilesByArch[arch];function finalize(path){info=staticFiles[path];if(typeof info==='function'){info=staticFiles[path]=info()}
return info}
if(hasOwn.call(staticFiles,originalPath)){return finalize(originalPath)}
if(path!==originalPath&&hasOwn.call(staticFiles,path)){return finalize(path)}});return info}
WebAppInternals.parsePort=port=>{let parsedPort=parseInt(port);if(Number.isNaN(parsedPort)){parsedPort=port}
return parsedPort};import{onMessage}from 'meteor/inter-process-messaging';onMessage('webapp-pause-client',async({arch})=>{WebAppInternals.pauseClient(arch)});onMessage('webapp-reload-client',async({arch})=>{WebAppInternals.generateClientProgram(arch)});function runWebAppServer(){var shuttingDown=!1;var syncQueue=new Meteor._SynchronousQueue();var getItemPathname=function(itemUrl){return decodeURIComponent(parseUrl(itemUrl).pathname)};WebAppInternals.reloadClientPrograms=function(){syncQueue.runTask(function(){const staticFilesByArch=Object.create(null);const{configJson}=__meteor_bootstrap__;const clientArchs=configJson.clientArchs||Object.keys(configJson.clientPaths);try{clientArchs.forEach(arch=>{generateClientProgram(arch,staticFilesByArch)});WebAppInternals.staticFilesByArch=staticFilesByArch}catch(e){Log.error('Error reloading the client program: '+e.stack);process.exit(1)}})};WebAppInternals.pauseClient=function(arch){syncQueue.runTask(()=>{const program=WebApp.clientPrograms[arch];const{unpause}=program;program.paused=new Promise(resolve=>{if(typeof unpause==='function'){program.unpause=function(){unpause();resolve()}}else{program.unpause=resolve}})})};WebAppInternals.generateClientProgram=function(arch){syncQueue.runTask(()=>generateClientProgram(arch))};function generateClientProgram(arch,staticFilesByArch=WebAppInternals.staticFilesByArch){const clientDir=pathJoin(pathDirname(__meteor_bootstrap__.serverDir),arch);const programJsonPath=pathJoin(clientDir,'program.json');let programJson;try{programJson=JSON.parse(readFileSync(programJsonPath))}catch(e){if(e.code==='ENOENT')return;throw e}
if(programJson.format!=='web-program-pre1'){throw new Error('Unsupported format for client assets: '+JSON.stringify(programJson.format))}
if(!programJsonPath||!clientDir||!programJson){throw new Error('Client config file not parsed.')}
archPath[arch]=clientDir;const staticFiles=(staticFilesByArch[arch]=Object.create(null));const{manifest}=programJson;manifest.forEach(item=>{if(item.url&&item.where==='client'){staticFiles[getItemPathname(item.url)]={absolutePath:pathJoin(clientDir,item.path),cacheable:item.cacheable,hash:item.hash,sourceMapUrl:item.sourceMapUrl,type:item.type};if(item.sourceMap){staticFiles[getItemPathname(item.sourceMapUrl)]={absolutePath:pathJoin(clientDir,item.sourceMap),cacheable:!0}}}});const{PUBLIC_SETTINGS}=__meteor_runtime_config__;const configOverrides={PUBLIC_SETTINGS};const oldProgram=WebApp.clientPrograms[arch];const newProgram=(WebApp.clientPrograms[arch]={format:'web-program-pre1',manifest:manifest,version:()=>WebAppHashing.calculateClientHash(manifest,null,configOverrides),versionRefreshable:()=>WebAppHashing.calculateClientHash(manifest,type=>type==='css',configOverrides),versionNonRefreshable:()=>WebAppHashing.calculateClientHash(manifest,(type,replaceable)=>type!=='css'&&!replaceable,configOverrides),versionReplaceable:()=>WebAppHashing.calculateClientHash(manifest,(_type,replaceable)=>{if(Meteor.isProduction&&replaceable){throw new Error('Unexpected replaceable file in production')}
return replaceable},configOverrides),cordovaCompatibilityVersions:programJson.cordovaCompatibilityVersions,PUBLIC_SETTINGS});const manifestUrlPrefix='/__'+arch.replace(/^web\./,'');const manifestUrl=manifestUrlPrefix+getItemPathname('/manifest.json');staticFiles[manifestUrl]=()=>{if(Package.autoupdate){const{AUTOUPDATE_VERSION=Package.autoupdate.Autoupdate.autoupdateVersion}=process.env;if(AUTOUPDATE_VERSION){newProgram.version=AUTOUPDATE_VERSION}}
if(typeof newProgram.version==='function'){newProgram.version=newProgram.version()}
return{content:JSON.stringify(newProgram),cacheable:!1,hash:newProgram.version,type:'json'}};generateBoilerplateForArch(arch);if(oldProgram&&oldProgram.paused){oldProgram.unpause()}}
const defaultOptionsForArch={'web.cordova':{runtimeConfigOverrides:{DDP_DEFAULT_CONNECTION_URL:process.env.MOBILE_DDP_URL||Meteor.absoluteUrl(),ROOT_URL:process.env.MOBILE_ROOT_URL||Meteor.absoluteUrl()}},'web.browser':{runtimeConfigOverrides:{isModern:!0}},'web.browser.legacy':{runtimeConfigOverrides:{isModern:!1}}};WebAppInternals.generateBoilerplate=function(){syncQueue.runTask(function(){Object.keys(WebApp.clientPrograms).forEach(generateBoilerplateForArch)})};function generateBoilerplateForArch(arch){const program=WebApp.clientPrograms[arch];const additionalOptions=defaultOptionsForArch[arch]||{};const{baseData}=(boilerplateByArch[arch]=WebAppInternals.generateBoilerplateInstance(arch,program.manifest,additionalOptions));program.meteorRuntimeConfig=JSON.stringify({...__meteor_runtime_config__,...(additionalOptions.runtimeConfigOverrides||null)});program.refreshableAssets=baseData.css.map(file=>({url:bundledJsCssUrlRewriteHook(file.url)}))}
WebAppInternals.reloadClientPrograms();var app=connect();var rawConnectHandlers=connect();app.use(rawConnectHandlers);app.use(compress({filter:shouldCompress}));app.use(cookieParser());app.use(function(req,res,next){if(RoutePolicy.isValidUrl(req.url)){next();return}
res.writeHead(400);res.write('Not a proxy');res.end()});app.use(function(request,response,next){request.query=qs.parse(parseUrl(request.url).query);next()});function getPathParts(path){const parts=path.split('/');while(parts[0]==='')parts.shift();return parts}
function isPrefixOf(prefix,array){return(prefix.length<=array.length&&prefix.every((part,i)=>part===array[i]))}
app.use(function(request,response,next){const pathPrefix=__meteor_runtime_config__.ROOT_URL_PATH_PREFIX;const{pathname,search}=parseUrl(request.url);if(pathPrefix){const prefixParts=getPathParts(pathPrefix);const pathParts=getPathParts(pathname);if(isPrefixOf(prefixParts,pathParts)){request.url='/'+pathParts.slice(prefixParts.length).join('/');if(search){request.url+=search}
return next()}}
if(pathname==='/favicon.ico'||pathname==='/robots.txt'){return next()}
if(pathPrefix){response.writeHead(404);response.write('Unknown path');response.end();return}
next()});app.use(function(req,res,next){WebAppInternals.staticFilesMiddleware(WebAppInternals.staticFilesByArch,req,res,next)});app.use((WebAppInternals.meteorInternalHandlers=connect()));var packageAndAppHandlers=connect();app.use(packageAndAppHandlers);var suppressConnectErrors=!1;app.use(function(err,req,res,next){if(!err||!suppressConnectErrors||!req.headers['x-suppress-error']){next(err);return}
res.writeHead(err.status,{'Content-Type':'text/plain'});res.end('An error message')});app.use(async function(req,res,next){if(!appUrl(req.url)){return next()}else if(req.method!=='HEAD'&&req.method!=='GET'){const status=req.method==='OPTIONS'?200:405;res.writeHead(status,{'Allow':'OPTIONS, GET, HEAD','Content-Length':'0',})
res.end()}else{var headers={'Content-Type':'text/html; charset=utf-8'};if(shuttingDown){headers.Connection='Close'}
var request=WebApp.categorizeRequest(req);if(request.url.query&&request.url.query.meteor_css_resource){headers['Content-Type']='text/css; charset=utf-8';headers['Cache-Control']='no-cache';res.writeHead(200,headers);res.write('.meteor-css-not-found-error { width: 0px;}');res.end();return}
if(request.url.query&&request.url.query.meteor_js_resource){headers['Cache-Control']='no-cache';res.writeHead(404,headers);res.end('404 Not Found');return}
if(request.url.query&&request.url.query.meteor_dont_serve_index){headers['Cache-Control']='no-cache';res.writeHead(404,headers);res.end('404 Not Found');return}
const{arch}=request;assert.strictEqual(typeof arch,'string',{arch});if(!hasOwn.call(WebApp.clientPrograms,arch)){headers['Cache-Control']='no-cache';res.writeHead(404,headers);if(Meteor.isDevelopment){res.end(`No client program found for the ${arch} architecture.`)}else{res.end('404 Not Found')}
return}
await WebApp.clientPrograms[arch].paused;return getBoilerplateAsync(request,arch).then(async({stream,statusCode,headers:newHeaders})=>{if(!statusCode){statusCode=res.statusCode||200}
if(newHeaders){Object.assign(headers,newHeaders)}
if(request?.path?.startsWith('/amp/')||request?.path==='/amp'){const[error,html]=await to(streamToString(stream));if(error){debug.error(error);Meteor._debug('Error when transforming stream to html',err);res.writeHead(500,headers);res.end();stream.destroy();throw new Error(error)}
const[err,amp]=await to(html2amp(html,{optimize:!0,gaConfigPath:'../web.browser/app/analyticsAMP.json',cwd:__meteor_bootstrap__.serverDir}));if(err){debug.error(err);Meteor._debug('Error when transforming html to amp',err);stream.destroy();throw new Error(err)}
res.writeHead(statusCode,headers);res.write(amp);res.end();stream.destroy()}else{res.writeHead(statusCode,headers);stream.pipe(res,{end:!0})}}).catch(error=>{Log.error('Error running template: '+error.stack);res.writeHead(500,headers);res.end()})}});app.use(function(req,res){res.writeHead(404);res.end()});var httpServer=createServer(app);var onListeningCallbacks=[];httpServer.setTimeout(SHORT_SOCKET_TIMEOUT);httpServer.on('request',WebApp._timeoutAdjustmentRequestCallback);httpServer.on('clientError',(err,socket)=>{if(socket.destroyed){return}
if(err.message==='Parse Error'){socket.end('HTTP/1.1 400 Bad Request\r\n\r\n')}else{socket.destroy(err)}});_.extend(WebApp,{connectHandlers:packageAndAppHandlers,rawConnectHandlers:rawConnectHandlers,httpServer:httpServer,connectApp:app,suppressConnectErrors:function(){suppressConnectErrors=!0},onListening:function(f){if(onListeningCallbacks)onListeningCallbacks.push(f);else f()},startListening:function(httpServer,listenOptions,cb){httpServer.listen(listenOptions,cb)}});exports.main=argv=>{WebAppInternals.generateBoilerplate();const startHttpServer=listenOptions=>{WebApp.startListening(httpServer,listenOptions,Meteor.bindEnvironment(()=>{if(process.env.METEOR_PRINT_ON_LISTEN){console.log('LISTENING')}
const callbacks=onListeningCallbacks;onListeningCallbacks=null;callbacks.forEach(callback=>{callback()})},e=>{console.error('Error listening:',e);console.error(e&&e.stack)}))};let localPort=process.env.PORT||0;let unixSocketPath=process.env.UNIX_SOCKET_PATH;if(unixSocketPath){if(cluster.isWorker){const workerName=cluster.worker.process.env.name||cluster.worker.id
unixSocketPath+="."+workerName+".sock"}
removeExistingSocketFile(unixSocketPath);startHttpServer({path:unixSocketPath});const unixSocketPermissions=(process.env.UNIX_SOCKET_PERMISSIONS||"").trim();if(unixSocketPermissions){if(/^[0-7]{3}$/.test(unixSocketPermissions)){chmodSync(unixSocketPath,parseInt(unixSocketPermissions,8))}else{throw new Error("Invalid UNIX_SOCKET_PERMISSIONS specified")}}
const unixSocketGroup=(process.env.UNIX_SOCKET_GROUP||"").trim();if(unixSocketGroup){const unixSocketGroupInfo=whomst.sync.group(unixSocketGroup);if(unixSocketGroupInfo===null){throw new Error("Invalid UNIX_SOCKET_GROUP name specified")}}
registerSocketFileCleanup(unixSocketPath)}else{localPort=isNaN(Number(localPort))?localPort:Number(localPort);if(/\\\\?.+\\pipe\\?.+/.test(localPort)){startHttpServer({path:localPort})}else if(typeof localPort==='number'){startHttpServer({port:localPort,host:process.env.BIND_IP||'0.0.0.0'})}else{throw new Error('Invalid PORT specified')}}
return'DAEMON'}}
var inlineScriptsAllowed=!0;WebAppInternals.inlineScriptsAllowed=function(){return inlineScriptsAllowed};WebAppInternals.setInlineScriptsAllowed=function(value){inlineScriptsAllowed=value;WebAppInternals.generateBoilerplate()};var sriMode;WebAppInternals.enableSubresourceIntegrity=function(use_credentials=!1){sriMode=use_credentials?'use-credentials':'anonymous';WebAppInternals.generateBoilerplate()};WebAppInternals.setBundledJsCssUrlRewriteHook=function(hookFn){bundledJsCssUrlRewriteHook=hookFn;WebAppInternals.generateBoilerplate()};WebAppInternals.setBundledJsCssPrefix=function(prefix){var self=this;self.setBundledJsCssUrlRewriteHook(function(url){return prefix+url})};var additionalStaticJs={};WebAppInternals.addStaticJs=function(contents){additionalStaticJs['/'+sha1(contents)+'.js']=contents};WebAppInternals.getBoilerplate=getBoilerplate;WebAppInternals.additionalStaticJs=additionalStaticJs;runWebAppServer()
2 Likes

And that isn’t even minified that agressively - you have even more fun when all your variables and functions are replaced with single characters;

1 Like