electron-userland / electron-compile

DEPRECATED: Electron supporting package to compile JS and CSS in Electron applications
1.01k stars 99 forks source link

Would this project benefit from a plugin-based architecture? #309

Open crdrost opened 6 years ago

crdrost commented 6 years ago

Hi electron-compile folks, I am a big fan of this project and the idea of not having to write my own precompilation steps. I like the whole electron-forge toolkit.

I had some difficulty which led to me reading your source code and eventually writing my own build system for my application rather than using electron-forge: the problem was specifically that in production, project-local file: URIs were being mapped to text responses complaining about having to be compiled twice, and the software that was doing it was a proprietary module that I could not freely modify. And it was extensions like .json, .wasm, .res that I am not sure electron-compile even has any business compiling, but there they were:

Failed to compile C:/Users/drostc/electron-sfs-kiosk/out/electron-sfs-kiosk-win32-x64/resources/app/src/docroot/libs/PDFNetJSFull/WebViewer/lib/html5/pdf/PDFNetCFullWasm.br.wasm: Asked to compile C:/Users/drostc/electron-sfs-kiosk/out/electron-sfs-kiosk-win32-x64/resources/app/src/docroot/libs/PDFNetJSFull/WebViewer/lib/html5/pdf/PDFNetCFullWasm.br.wasm in production, is this file not precompiled?
Error: Asked to compile C:/Users/drostc/electron-sfs-kiosk/out/electron-sfs-kiosk-win32-x64/resources/app/src/docroot/libs/PDFNetJSFull/WebViewer/lib/html5/pdf/PDFNetCFullWasm.br.wasm in production, is this file not precompiled?
    at C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:336:15
    at Generator.next (<anonymous>)
    at step (C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:47:191)
    at C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:47:361
    at <anonymous>

Failed to compile C:/Users/drostc/electron-sfs-kiosk/out/electron-sfs-kiosk-win32-x64/resources/app/src/docroot/libs/PDFNetJSFull/WebViewer/lib/html5/pdf/pdfnet.res: Asked to compile C:/Users/drostc/electron-sfs-kiosk/out/electron-sfs-kiosk-win32-x64/resources/app/src/docroot/libs/PDFNetJSFull/WebViewer/lib/html5/pdf/pdfnet.res in production, is this file not precompiled?
Error: Asked to compile C:/Users/drostc/electron-sfs-kiosk/out/electron-sfs-kiosk-win32-x64/resources/app/src/docroot/libs/PDFNetJSFull/WebViewer/lib/html5/pdf/pdfnet.res in production, is this file not precompiled?
    at C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:336:15
    at Generator.next (<anonymous>)
    at step (C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:47:191)
    at C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:47:361
    at <anonymous>

Failed to compile C:/Users/drostc/electron-sfs-kiosk/out/electron-sfs-kiosk-win32-x64/resources/app/src/docroot/libs/PDFNetJSFull/WebViewer/lib/html5/Resources/i18n/translation-en.json: Cannot read property 'get' of null
TypeError: Cannot read property 'get' of null
    at C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:316:34
    at Generator.next (<anonymous>)
    at step (C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:47:191)
    at C:\Users\drostc\electron-sfs-kiosk\out\electron-sfs-kiosk-win32-x64\resources\app\node_modules\electron-compile\lib\compiler-host.js:47:361
    at <anonymous>

Note that it is even a little weirder than that because the .br.wasm file is not just WebAssembly but pre-Brotli-compressed WebAssembly: it ideally would want me to serve a Content-Encoding: br header, though I'm not sure I could achieve that on the file: protocol specifically.

This is somewhat related also to the problem #249 but the solution provided there doesn't really help.

I think what I am really looking for in order to use Forge hence Compile again is something like a .compilerc.js file or so: I would need some ability to plug in compilers for the steps that are being incorrectly compiled. So the idea is that Forge require()s this file and allows it to change the runtime state of electron-compile before electron-compile works properly. That file would contain some sort of code like,

const comp = require('electron-compile');

// could also steal configuration right from another file like #308 suggests
const tsConfig = require('./tsconfig'); 

// maybe this is shorthand for sending explicitly no config and letting Babel read its own JSON files?
const babel = comp.babel(null);

const config = new comp.Config();
module.exports = config;

// we want typescript to pass through `comp.tsc` but NOT comp.babel:
config.register(/\.tsx?$/i, comp.tsc(tsConfig));

// if we wanted comp.babel maybe compilers would have a `.pipeTo()` method.

// maybe we also use Webpack which creates some `bundle.js` which we can't pass to Babel, but we
// have other js files which we do need to. Maybe follow Express routing rules -- first to match wins?
config.register(/[\\/]bundle.js$/, comp.passThrough('text/javascript'));
config.register('js', babel); // string for common extensions? 

// as above, maybe I need to handle WASM myself:
config.register('wasm', comp.handle(async path => {
  // not sure what would be needed in here but something like:
  const extraHeaders =/\.br\.wasm/i.exec(path)? { 'Content-Encoding': 'br' } : undefined;
  return { type: 'file', path, type: 'application/wasm', extraHeaders };
}));

// otherwise for LESS, SCSS, etc. just use the defaults:
config.registerDefaultHandlers();

So the idea is that there is some internal data format for the objects created by compilers which knows about several types of basic operations like it can serve files by path, maybe can also serve a stream or whatever. There is a class containing a compiler configuration, which is a sort of routing table to certain "compilers" (maybe we would rather call them "handlers" so that not too many things have the name 'compiler' here?) -- each of those compilers then is responsible for being a function from either the file URI or the path it resolves to on the filesystem, to the internal data format.

Would this be an interesting direction for a new major version? Or do you feel like that's too big of a scope creep and the solution is instead precisely what I ended up doing, "stop trying to jam strange proprietary modules into our build system, it's not that hard to roll your own"...?

Basically I am thinking that once you have this and it's the Documented Way To Do Things, you have people building module ecosystems to service their niches, so your users become contributors at some level. But it's also possible that the core devs of electron-compile, electron-forge feel like the project is basically "finished" and does not need to have those sorts of ambitions, which is totally cool because we do all have other stuff to do in our jobs.