Last year Aurelia introduced a version that can be put in a script tag and you are ready to go! it was named aurelia-script
aurelia-script
This repo is the home for Aurelia's concatenated script-tag-ready build.
To keep up to date on Aurelia, please visit and subscribe to the official blog and our email list. We also invite you to follow us on twitter. If you have questions, please join our community on Gitter or use stack overflow. Documentation can be found in our developer hub.
Getting started with Aurelia Script
Simple examples
In the good old day, you chuck in a script tag into your html and start writing app. Aurelia Script is a way to help you return to that, with Aurelia. Simply add:
<script src='https://unpkg.com/aurelia-script@1.5.2'></script>
into your main html and you are ready to go, like the following:
<script>
au
.start({
debug: true,
// root: 'app.js', // can be ommitted, default is
…
Aurelia is conventions based, you need an <name>.html
file with a template tag
and a <name>.js
file with a class and that's it you now have a component to be used anywhere else. the fact that Aurelia is conventions based, means that
you can go from concept to prototype to feature with the same files you started with.
Setting up with Electron
When playing with this I found out that the router finds for these convention based files in the root of the server, using the dynamic imports, (import()
) so this brings two things to the table, if you want to use aurelia-script
you need to take into consideration that it is meant for browsers with dynamic imports support, and the other... is that loading from file://
won't work at all!
this can be fixed quite easily, just run a small static server to serve your content, I chose koa.js
but you can easily use a static server package out there
AngelMunoz / AuExplorer
A small Proof of concept of an aurelia-script electron mixed app
AuExplorer
A small Proof of concept of an aurelia-script electron mixed app
pnpm install # or npm
pnpm start # or npm
It's a small sample and was done quick and dirty but to me shows how easy is to get started with aurelia-script
since aurelia is based on conventions if you need to grow out of the single script, you will do that quite easy
first of all our code in the index.js
file at the root is pretty simple
// imports
const Koa = require('koa');
const serve = require('koa-static');
const { resolve } = require('path');
const { spawn } = require('child_process');
const app = new Koa();
let elcProcess;
// I'm not sure how secure is this at all
app.use(serve(`${__dirname}/node_modules`));
app.use(serve(`${__dirname}/renderer`));
// get the correct electron bin for your platform
const electron = process.platform === 'win32' ? resolve('node_modules/.bin', 'electron.cmd') : resolve('node_modules/.bin', 'electron');
const indexFile = resolve(__dirname, 'main/index.js');
// after we successfully start our server, then spawn the electron process
app.listen(45789, '127.0.0.1', () => {
// you could also add argv arguments if you need
// like [indexFile, ...process.argv.slice(2)]
elcProcess = spawn(electron, [indexFile], {});
// bind process monitoring if you need
elcProcess.on('error', onElcError);
elcProcess.stdout.on('data', onElcData);
elcProcess.on('exit', onElcExit)
});
function onElcData(chunk) {/*...*/}
function onElcError(err) {/*...*/}
function onElcExit(code, signal) {/*...*/}
nothing fancy just your every other day node server.
Inside the renderer we have our aurelia app which starts pretty much like the one I showed you in the codesandbox above
<script src="/aurelia-script/dist/aurelia_router.umd.js"></script>
<script src="/localforage/dist/localforage.js"></script>
<script src="/dayjs/dayjs.min.js"></script>
<script>
const aurelia = new au.Aurelia();
aurelia
.use
.standardConfiguration()
.developmentLogging();
aurelia
.start()
.then(() => aurelia.setRoot(`app.js`, document.body))
.catch(ex => {
document.body.textContent = `Bootstrap error: ${ex}`;
});
</script>
you might be thinking why do I need to manually call these libraries! iugh! it's 2019!
well I just tried this as a proof of concept, so there might be better options on how to do this, perhaps parcel?, or you can just build your app and spit the bundle in there, but the principal idea of this sample is to go for simplicity and just put in some stuff together and just work it out!
other thing to have into consideration is that I turned off node integration
for the sample and added a preload script to add the ipcRenderer
to the window object so I could just send back and forth messages to the main
process (more on that later on).
Let's take a look to our app.js file
// simple class
export class App {
constructor() {
this.message = "Hello world";
this.menuOpen = false;
// bind process events to your class functions
ipcRenderer.on('get:home:ans', this.setHomePath.bind(this));
}
// normal life cycle methods available!
async activate() {
const home = await localforage.getItem('home');
if (!home) {
// send a message to the main process
ipcRenderer.send('get:home');
}
}
// just like in any other aurelia app!
configureRouter(config, router) {
config.options.pushState = true;
config.map([
{
route: ["", "home"],
name: "home",
// relative to the root of the server
moduleId: "pages/home.js",
title: "Home",
nav: true
},
{
route: "contact",
name: "contact",
moduleId: "pages/contact.js",
title: "Contact",
nav: true
}
]);
this.router = router;
}
toggleMenu() {/*...*/}
async setHomePath(event, path) {/*...*/}
}
now you may wondering, how can the ipcRenderer be just there? no require no import no anything, well that's because we have a small preload script that does that for us, I'll show the createWindow
function at the index.js
in the main directory and omit the rest.
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
/*...*/
webPreferences: {
// call the preload script
preload: `${__dirname}/preload.js`,
// disable node integration for this window
nodeIntegration: false
}
/*...*/
})
// and load the index.html of the app.
mainWindow.loadURL('http://localhost:45789')
/*...*/
}
and then in our preload script
const { ipcRenderer } = require('electron');
window.ipcRenderer = ipcRenderer;
window.PATH_DIVIDER = process.platform === 'win32' ? '\\' : '/';
you can use this script to expose node internals if you need them, like the inAppPurchase API
but in my short thinking you should be able to accomplish most of the things by just using the ipc
-inter-process communication.
Thoughts
Well this was a cool thing to experiment and try on, it feels really great to just pull a script tag and have all the power of aurelia and it's conventions at your hands!
for example if you wanted all of the power of vue, the most ideal is to have vue
files but when you use a script tag, that's not really a possibility you would need to change your vue components into other syntax which doesn't match the same experience of the vue
files, I feel the same applies to other frameworks out there at the moment.
Extra
if you wonder how Dependecy injection and bindable decorators you would normally use fit in aurelia-script
you can check this sample out
Please share your thoughts and comments below and have an awesome week!
Top comments (2)
It might be an easy fix for experimentation and Aurelia and Electron are great but you should not ship a production Electron app with a built in web server simply because
aurelia-script
doesn't work onfile://
.Most of time you'll be lucky and port 45789 will be available on the machine but Aurelia works perfectly well with Electron without exposing a server on localhost.
Yes, this was intended to test aurelia-script within electron and any potential gotchas (like the
file://
part). I just wanted to share my experience about using itI don't intend anyone to ship aurelia-script to production and I'm well aware of some aurelia + electron solutions