How do I use Sails.js in Node-Webkit? - node.js

I tried to create an application with Node-Webkit and Sails.js. My API works fine, I get the JSON I need, but when integrated with Node-Webkit does not start the server.
My package.json contains:
{
   "name": "app-sails"
   "main": "front/index.html"
   "window": {
     "toolbar": true,
     "width": 1024,
     "height": 600,
     "title": "Test Application"
   },
   "scripts": {
     "start": "node server/app.js"
   }
}
The index.html is the main page you get when you use the generator angular.js yeoman and contains calls to the server that I have with sails.js. In the web running, but not with Node-Webkit.
When I run the .nw, I can see my index.html correctly; but without the data it throws the sails server.
I appreciate any help.

I recently wrote a small article on this, you can check it out here: https://medium.com/unhandled-exception/sailsjs-and-node-webkit-4ccb8f810add
Basically you just need to execute sails using require as soon as the node-webkit window is loaded. This goes in your app.js file:
exports.onLoad = function() {
var nwGUI = window.require('nw.gui');
nwGUI.Window.get(window).on('loaded', function() {
if (loaded) {
return;
}
window.location.href = "http://localhost:1337/";
loaded = true;
});
try {
sails = require('sails');
} catch (e) {
console.error('To run an app using `node app.js`, you usually need to have a version of `sails` installed in the same directory as your app.');
console.error('To do that, run `npm install sails`');
console.error('');
console.error('Alternatively, if you have sails installed globally (i.e. you did `npm install -g sails`), you can use `sails lift`.');
console.error('When you run `sails lift`, your app will still use a local `./node_modules/sails` dependency if it exists,');
console.error('but if it doesn\'t, the app will run with the global sails instead!');
return;
}
// Try to get `rc` dependency
try {
rc = require('rc');
} catch (e0) {
try {
rc = require('sails/node_modules/rc');
} catch (e1) {
console.error('Could not find dependency: `rc`.');
console.error('Your `.sailsrc` file(s) will be ignored.');
console.error('To resolve this, run:');
console.error('npm install rc --save');
rc = function() {
return {};
};
}
}
// Start server
sails.lift(rc('sails'));
}
and this on your .html entry point:
<html>
<head>
<title>Welcome!</title>
</head>
<body onload="process.mainModule.exports.onLoad();">
<h1>hi!</h1>
</body>
</html>
As you can see, most of that app.jss file is basically the same that comes out when you do a
sails new
I just wrapped everything up and executed that callback onload
If you want you can always check out the article and the full github repo for a more detailed version of the code.
Oh! And don't forget to update your package.json and add:
{
...
"node-main": "app.js",
...
}

You should load the Sails-Page not your index.html.
One thing you could do is (in your HTML)
window.location.href = "http://localhost:1337/";

Related

ElectronJS crashes on dialog.showOpenDialog(...)

I'm trying to prompt an "open file" dialog box, and I found dialog.showOpenDialog(...) in the electron docs.
I've added this line to a few different projects now, with the result of crashing as soon as that line hits. I would see the file explorer dialog window open for a second, then it crashed. The console gives me no error message, the last thing it prints is Promise { <pending> }.
What I've tried:
Adding dialog.showOpenDialog(...) to the official vscode debugging example, to see if it picks up any errors. It always crashes as soon as it reaches that line, with no error message.
Removing my node_modules folder and reinstalling electron using npm install electron --save-dev
Running the app using a global electron command electron .
Uninstalling global electron using npm uninstall -g electron and using a local npm start
Checking if my node packages are out of date using `npm outdate
Running the app using --disable-gpu argument
I'm using Ubuntu 19.04, not a VM, but I also tested it on Ubuntu 18.04 in a VM.
One interesting note is that when I tried to use an html form button with a type = file to accomplish this same task, it also crashed as soon as the file explorer dialog box opened in the electron app. BUT it did work when I opened the html page in a regular web browser.
Here's my main.js
const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
win.loadFile('index.html')
// Open the DevTools.
win.webContents.openDevTools()
// Emitted when the window is closed.
win.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
win = null
})
const { dialog } = require('electron')
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] })) //*****THIS LINE HERE
}
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
Here's my package.json
{
"name": "electron-demo",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^7.1.2"
}
}

How do I configure Intern 4 to use RequireJS?

I've got RequireJS installed in my node_modules directory, and my intern.json file has:
"node": {
"loader": "requirejs"
},
However, when I run "npx intern", it fails with:
Error: Loader script requirejs did not register a loader callback
at
at
Is there a way to get Intern 4 to use RequireJS?
To use a particular loader, Intern needs a 'loader' script that will actually initialize the loader and handle loading modules with it. Intern includes loader scripts for several loaders, such as Dojo 1, Dojo, and SystemJS. It doesn't include a loader script for RequireJS, but you can add one fairly easily.
A simple script for RequireJS would look like:
// your_project/reqjs.js
intern.registerLoader(function(options) {
function initLoader(requirejs) {
// Configure requireJS -- use options passed in through the intern.json
// config, and add anything else
requirejs.config(options);
// This is the function Intern will actually call to load modules
return function(modules) {
return new Promise(function(resolve, reject) {
requirejs(modules, function() {
resolve();
}, function(error) {
reject(error);
});
});
};
};
if (typeof window !== 'undefined') {
return intern
.loadScript('node_modules/requirejs/require.js')
.then(function() {
return initLoader(window.requirejs);
});
} else {
return initLoader(require('requirejs'));
}
});
Note that Intern doesn't use loaders to actually retrieve modules for its own use (which is why the resolve call above doesn't include the loaded modules), it only uses them to load test suites. The suites themselves may use the loader normally.
You would use the script in your config with
"node": {
"loader": "./reqjs.js"
}

Can't use Worker-Loader with Vuejs and Webpack

I am trying to get web workers up and running with Vue cli3 and I'm having trouble getting it to work.
I want to use the following package, worker-loader (and not vue-worker), as it looks well maintained and with more contributions.
Following their tutorial I attempted to modify webpack using the vue cli as follows:
module.exports = {
chainWebpack: config => {
config.module
.rule('worker-loader')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
.end()
}
}
which I hope should match their
{
module: {
rules: [
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' }
}
]
}
}
which can be read here (https://github.com/webpack-contrib/worker-loader). I tried to follow the documentation for vue cli3 as best I could (found here: https://cli.vuejs.org/guide/webpack.html#simple-configuration).
My component is pretty simple:
import Worker from 'worker-loader!./../../sharedComponents/equations/recurringTimeComposer.js';
<...>
watch:{
recurringPaymentReturnObj: function(newVal, oldVal){
const myWorker = new Worker;
myWorker.postMessage({ hellothere: 'sailor' });
myWorker.onmessage = (e) => {
console.log('value of e from message return', e.data);
}
}
<...>
and in my ./../../sharedComponents/equations/recurringTimeComposer.js file I have:
onmessage = function(e) {
console.log('Message received from main script: ', e.data);
// var workerResult = 'Result: ' + e.data;
// console.log('Posting message back to main script');
postMessage('hello back handsome');
close();
}
I keep getting the error message:
ReferenceError: window is not defined a162426ab2892af040c5.worker.js:2:15
After some googling I came across this post: https://github.com/webpack/webpack/issues/6642, which suggests that the best way to fix this is to add the following to webpack:
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
publicPath: 'http://localhost:3000',
globalObject: 'this'
},
After modifying my vue.config.js file I have:
module.exports = {
chainWebpack: config => {
config.module
.rule('worker-loader')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
.end()
config
.output
.path(path.join(__dirname, 'dist'))
.filename('bundle.js')
.publicPath('http://localhost:8080')
.globalObject('this')
}
}
...but still I am getting the window is not defined error.
Does anyone know what is going wrong? It seems to be a weird error in webpack.
Thanks!
EDIT: oh yeah, here is the MDN page for webworker as well: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers.
Being new to Javascript I kept coming back to this issue when trying to use web workers with VueJS. I never managed to make it work with vue-worker or worker-loader.
It is now 2020 and Google has released worker-plugin.
To use it create a module my-worker with two files index.js and worker.js.
index.js creates the module:
const worker = new Worker('./worker.js', { type: 'module' });
const send = message => worker.postMessage({
message
})
export default {
worker,
send
}
worker.js contains the logic:
import _ from 'lodash'
addEventListener("message", async event => {
let arrayToReverse = event.data.message.array
let reversedArray = _.reverse(arrayToReverse)
// Send the reversed array
postMessage(reversedArray)
});
You will also need to update your vue.config.js to use the WorkerPlugin:
const WorkerPlugin = require('worker-plugin')
module.exports = {
configureWebpack: {
output: {
globalObject: "this"
},
plugins: [
new WorkerPlugin()
]
}
};
Now you can use you worker in your components:
Import it with import worker from '#/my-worker'.
Setup a listener in the mounted() lifecycle hook with worker.worker.onmessage = event => { // do something when receiving postMessage }
Start the worker with worker.send(payload).
I set up a starter code on github. I still haven't managed to make HMR work though...
This works for me (note the first line):
config.module.rule('js').exclude.add(/\.worker\.js$/)
config.module
.rule('worker-loader')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
The first line excludes worker.js files, so two loaders wouldn't fight over the same js file
is this what you need ? Vue issue with worker-loader
Updating from the classic vue & webpack config, I found out that to make this one work, I needed to deactivate parallelization.
// vue.config.js
module.exports = {
parallel: false,
chainWebpack: (config) => {
config.module
.rule('worker')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
.end();
}
};
I tried add web worker to a vue-cli4 project, and here is what I found:
using worker-loader and make configs in chainWebpack:
HMR works fine, but sourcemap broke, it show babel transformed code.
using worker-plugin as #braincoke mentioned:
HMR broke, but sourcemap works fined. and eslint broke while suggested disable all worker js file eslint instead.
Finally, My solution is tossing vue-cli away, and embrace vite.It support worker natively, and all just go fine now. (I think upgrade webpack to v5 can solve this, but i never tried.)

Accessing Meteor settings in Mocha

I want to do write some unit tests with mocha but for some tests i need to access the Meteor.settings which are read by meteor from a file: config/settings.json
Normally i import meteor by:
import { Meteor } from 'meteor/meteor'
But when i try to import this in my test, i get the error: ERROR: Cannot find module 'meteor/meteor' (i also tried to do relative path).
I run my test by this:
"wdio-test": "wdio tests/config/wdio.mocha.conf.js"
and
npm run wdio-test
Anyone can help importing Meteor or accessing the settings file (If possible without file IO operations)?
Stub the meteor core and the settings object:
import { MeteorStubs } from 'meteor/velocity:meteor-stubs';
describe('tests', function() {
beforeEach(function() {
MeteorStubs.install();
Meteor.settings.public.foo = 'bar';
});
afterEach(function() {
MeteorStubs.uninstall();
});
it('gets setting', function() {
chai.assert.equal(Meteor.settings.public.foo, 'bar');
});
});

Node-Webkit sharing data in node via exports

I'm experimenting with Node-Webkit lately, if I call sth like that;
exports.name = function() {
console.log('My name is Uğur');
};
Node-WebKit renderer throws a error:
"Uncaught ReferenceError: exports is not defined"
I couldn't understand, Is it caused by node-webkit or node.js itself. Since; 'node test.js'
works without problem.
You need to run this in the Node's context (not WebKit's context). To do that, specify the script in 'node-main' in the manifest.
Here is an example:
index.js:
exports.callback0 = function (win) {
}
index.html:
<body onload="process.mainModule.exports.callback0(window)">
package.json:
{
"name": "nw-demo",
"node-main": "index.js",
"main": "index.html"
}
HTH

Resources