Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Electron ES6 module import

Tags:

electron

Electron 3.0.0-beta.1 Node 10.2.0 Chromium 66.0.3359.181

The problem I'm having is importing a module. I created the following protocol:

protocol.registerFileProtocol('client', (request, callback) => {
    var url = request.url.substr(8);
    callback({path: path.join(__dirname, url)});
});

The output of the protocol is the correct path

"/Users/adviner/Projects/Client/src/ClientsApp/app.js"

I have the following module app.js with the following code:

export function square() {
    return 'hello';
}

in my index.html I import the module like so:

    <script type="module" >
        import square from 'client://app.js';
        console.log(square());
    </script>       

But I keep getting the error:

app.js/:1 Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.

I'm done searches but can't seem to find a solution. Can anyone suggest a way I can make this work?

Thanks

like image 707
adviner Avatar asked Jun 30 '18 08:06

adviner


3 Answers

This is a tricky question and i will refer to Electron#12011 and this GitHub Gist for a deeper explaination but the core learning is that the corresponding HTML spec, disallows import via file:// (For XSS reasons) and a protocol must have the mime types defined.

The file protocol you use client:// has to set the correct mime-types when serving the files. Currently i would guess they are not set when you define the protocol via protocol.registerBufferProtocol thus you recive a The server responded with a non-JavaScript MIME type of "", the gist above has a code sample on how to do it.

Edit: I just want to emphasize the other answers here do only cover the absolute minimum basics implementation with no consideration of exceptions, security, or future changes. I highly recommend taking the time and read trough the gist I linked.

like image 99
Hans Koch Avatar answered Oct 16 '22 20:10

Hans Koch


To confirm: this is there for security reasons.

However, in the event that you just need to get it deployed:

Change "target": "es2015" to "target": "es5" in your tsconfig.json file

like image 8
rob_james Avatar answered Oct 16 '22 21:10

rob_james


Quick Solution:

const { protocol } = require( 'electron' )
const nfs = require( 'fs' )
const npjoin = require( 'path' ).join
const es6Path = npjoin( __dirname, 'www' )

// <= v4.x
// protocol.registerStandardSchemes( [ 'es6' ] )

// >= v5.x
protocol.registerSchemesAsPrivileged([
  { scheme: 'es6', privileges: { standard: true } }
])

app.on( 'ready', () => {
  protocol.registerBufferProtocol( 'es6', ( req, cb ) => {
    nfs.readFile(
      npjoin( es6Path, req.url.replace( 'es6://', '' ) ),
      (e, b) => { cb( { mimeType: 'text/javascript', data: b } ) }
    )
  })
})
<script type="module" src="es6://main.js"></script>
like image 8
flcoder Avatar answered Oct 16 '22 19:10

flcoder