Durandal, Socket.io and require - sockets

I'm having a hard time setting up Durandal to include the socket io library.
I've tried a few methods, including the path in the main.js library but as it isn't a single js file, it has never worked.
If anyone has experience with this, I'd extremely appreciate it!!
Thanks
Edited with code,
requirejs.config({
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-3.1.0',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1',
'toastr' : '../lib/toastr/toastr',
'moment' : '../lib/moment/moment',
'when' : '../lib/when/when',
'flipclock': '../lib/flipclock/flipclock',
'require': '../lib/require/require'
},
shim: {
'bootstrap': {
deps: ['jquery'],
exports: 'jQuery'
}
}
});
define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'require', 'plugins/http'], function (system, app, viewLocator, require, http) {
var io = require('socket.io')(http);

In order to work you need to add socket.io to the paths config, as well as define a shim.
Make sure the path to socket io is setup properly.
paths: {
....
'socketio': 'PATH_TO/socket.io/socket.io'
},
shim: {
'socketio': {
'exports': 'io'
}
}
define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'bootstrap',
'socketio', 'knockout'],
function (system, app, viewLocator, bootstrap, io, ko) {
// if its on the same host
var testsocket = io.connect(window.location.hostname);
// otherwhise
var testsocket = io.connect(PATHTOSOCKET);
});
that should do the trick
EDIT:
Additionally it seems like you want to use the NPM package in the frontend, which is clearly not the way to go. Socket.IO creates a frontend proxy, which can be utilized the way described above.

You need to include socket.io in your requirejs configuration:
requirejs.config({
paths: {
...,
'socket': 'path/to/socket.io'
},
...
});
Then, you can access the library from within your application like such:
define([..., 'socket'],
function (..., socket) {
// body here with access to socket
socket.doSomething();
});

paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-3.1.0',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1',
'toastr' : '../lib/toastr/toastr',
'moment' : '../lib/moment/moment',
'when' : '../lib/when/when',
'flipclock': '../lib/flipclock/flipclock',
'require': '../lib/require/require',
'socket': '../lib/socket.io/lib/socket'
},
So I've included it in my requirejs configuration.
define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'require', 'plugins/http', 'socket'], function (system, app, viewLocator, require, http, socket) {
This seems to have help but now I'm getting,
Module name "events" has not been loaded yet for context: _. Use require([]) exception
. The page does load now, but I assume I must include "events" too?
The issues seems to be the standard require for socket io is something like this,
var io = require('socket.io')(http);
Which must resolve all the dependencies as the npm socket.io has modules within it. The requirejs path similar loads a single js file, were socket.io has many.

Related

How to pass options to babel plugin transform-modules-commonjs?

I create a Vue 2 project by Vue-Cli 5, then I want to remove "use strick" in the complied code.
As I Know, the #babel/plugin-transform-strick-mode may be enabled via #babel/plugin-transform-modules-commonjs, and the plugin is included in #babel/preset-env under the modules option.
But the Vue-Cli used a preset #vue/babel-preset-app by a plugin #vue/cli-plugin-babel for babel.
So my question is How pass strictMode: false as an option to the transform-modules-commonjs by #vue/babel-preset-app which preset is in the #vue/cli-plugin-babel ?
module.exports = {
presets: [["#vue/cli-plugin-babel/preset", { modules: "auto" }]],
plugins: [
// I tried this way, but it throw many errors like:
/**
ERROR in ./node_modules/axios/dist/node/axios.cjs 11:15-32
Module not found: Error: Can't resolve 'stream' in 'D:\workspace\cqset_offical_website\node_modules\axios\dist\node'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
- install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "stream": false }
*/
["#babel/plugin-transform-modules-commonjs", {}],
[
"component",
{
libraryName: "element-ui",
styleLibraryName: "theme-chalk",
},
],
],
};

Webpack with Babel lazy load module using ES6 recommended Import() approach not working

I'm trying to do code splitting and lazy loading with webpack using the import() method
import('./myLazyModule').then(function(module) {
// do something with module.myLazyModule
}
I'm getting
'import' and 'export' may only appear at the top level
Note top level imports are working fine, i'm just getting an issue when I try and using the dynamic variant of import()
var path = require('path');
module.exports = {
entry: {
main: "./src/app/app.module.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name]-application.js"
},
module: {
rules: [
{
test: /\.js$/,
use: [{
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}]
}
]
},
resolve : {
modules : [
'node_modules',
'bower_components'
]
},
devtool : "source-map"
}
EDIT:
If I change it so the syntax reads, it works.... but the chunk comments don't work to label the bundle. I'm confused because the documentation says the the following is depreciated.
The use of System.import in webpack did not fit the proposed spec, so
it was deprecated in webpack 2.1.0-beta.28 in favor of import().
System.import('./myLazyModule').then(function(module) {
// do something with module.myLazyModule
}
You need the plugin syntax-dynamic-import to be able to use the import() function with Babel.
Install it with:
npm install --save-dev #babel/plugin-syntax-dynamic-import
And add it to your plugins:
{
presets: ['es2015'],
plugins: ['#babel/plugin-syntax-dynamic-import']
}

localhost:3000/traceur SystemJS with AngularFire

I picked the getting started with Angular2 tutorial format and only added in the angularfire2 part.
I installed firebase and angularfire2 using the steps on the angularfire2 docs page
Below is my systemjs.config.js
/**
* System configuration for Angular 2 samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',
'angularfire2': 'npm:angularfire2'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'angular2-in-memory-web-api': {
main: './index.js',
defaultExtension: 'js'
},
angularfire2: {
main: 'index.js',
defautExtension: 'js'
}
}
});
})(this);
Then I am simply importing it like so:
import { AngularFireModule } from 'angularfire2';
Then I keep getting this error:
Any hint what is going on?
Your config maps angularfire2 to node_modules/angularfire2/index.js, which is written is es6, so SystemJS tries to compile it using traceur, and can not find it.
The easy fix would be to configure it so it loads the bundle in angular2/bundles/angularFire2.umd.js, not index.js.
So angularfire2 in packages
angularfire2: {
main: 'index.js'
needs to be changed to
angularfire2: {
main: 'bundles/angularFire2.umd.js'
Also, angularFire depends on Firebase, so, as #Jonathon Oates said in his answer, you need to provide configuration for Firebase too.
Thanks #artem — I was having the exact same problem!
You may also need to reference Firebase in your map too e.g.
'firebase': 'npm:firebase'
And add Firebase to your packages e.g.
'angularfire2': {
main: './bundles/angularFire2.umd.js',
defaultExtension: 'js'
},
'firebase': {
main: './firebase.js',
defaultExtension: 'js'
}
Otherwise you may see a new 404 error for Firebase.

Using Grunt to Mock Endpoints

I'm using Yeoman, Grunt, and Bower, to construct a platform for building a frontend independently of a a backend. The idea would be that all of my (AngularJS) controller, services, factories, etc live in this project, and get injected afterwards into my serverside codebase based off the result of grunt build.
My question is:
How can I mock endpoints so that the Grunt server responds to the same endpoints as my (Rails) App will?
At the moment I am using:
angular.module('myApp', ['ngResource'])
.run(['$rootScope', function ($rootScope) {
$rootScope.testState = 'test';
}]);
And then in each of my individual services:
mockJSON = {'foo': 'myMockJSON'}
And on every method:
if($rootScope.testState == 'test'){
return mockJSON;
}
else {
real service logic with $q/$http goes here
}
Then after grunt build, testState = 'test' gets removed.
This is clearly a relatively janky architecture. How can I avoid it? How can I have Grunt respond to the same endpoints as my app (some of which have dynamic params) apply some logic (if necessary), and serve out a json file (possibly dependent on path params)?
I've fixed this issue by using express to write a server that responds with static json.
First I created a directory in my project called 'api'. Within that directory I have the following files:
package.json:
{
"name": "mockAPI",
"version": "0.0.0",
"dependencies": {
"express": "~3.3.4"
}
}
Then I run npm install in this directory.
index.js:
module.exports = require('./lib/server');
lib/server.js:
express = require('express');
var app = express();
app.get('/my/endpoint', function(req, res){
res.json({'foo': 'myMockJSON'});
});
module.exports = app
and finally in my global Gruntfile.js:
connect: {
options: {
port: 9000,
hostname: 'localhost',
},
livereload: {
options: {
middleware: function (connect, options) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app),
require('./api')
];
}
}
},
Then the services make the requests, and the express server serves the correct JSON.
After grunt build, the express server is simply replaced by a rails server.
As of grunt-contrib-connect v.0.7.0 you can also just add your custom middleware to the existing middleware stack without having to manually rebuild the existing middleware stack.
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= config.app %>'
],
middleware: function(connect, options, middlewares) {
// inject a custom middleware into the array of default middlewares
middlewares.push(function(req, res, next) {
if (req.url !== '/my/endpoint') {
return next();
}
res.writeHead(200, {'Content-Type': 'application/json' });
res.end("{'foo': 'myMockJSON'}");
});
return middlewares;
}
}
},
See https://github.com/gruntjs/grunt-contrib-connect#middleware for the official documentation.
Alternatively you can use the grunt-connect-proxy to proxy everything that is missing in your test server to an actual backend.
It's quite easy to install, just one thing to remember when adding proxy to your livereload connect middleware is to add it last, like this:
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app),
proxySnippet
];
}
grunt-connect-prism is similar to the Ruby project VCR. It provides an easy way for front end developers to record HTTP responses returned by their API (or some other remote source) and replay them later. It's basically an HTTP cache, but for developers working on a Single Page Application (SPA). You can also generate stubs for API calls that don't exist, and populate them the way you want.
It's useful for mocking complex & high latency API calls during development. It's also useful when writing e2e tests for your SPA only, removing the server from the equation. This results in much faster execution of your e2e test suite.
Prism works by adding a custom connect middleware to the connect server provided by the grunt-contrib-connect plugin. While in 'record' mode it will generate a file per response on the filesystem with content like the following:
{
"requestUrl": "/api/ponies",
"contentType": "application/json",
"statusCode": 200,
"data": {
"text": "my little ponies"
}
}
DISCLAIMER: I'm the author of this project.
You can use Apache proxy and connect your REST server with gruntjs.
Apache would do this:
proxy / -> gruntjs
proxy /service -> REST server
you would use your application hitting Apache and angular.js application would think that is talking with itself so no cross domain problem.
Here is a great tutorial on how to set this up:
http://alfrescoblog.com/2014/06/14/angular-js-activiti-webapp-with-activiti-rest/
Just my alternative way that based on Abraham P's answer. It does not need to install express within 'api' folder. I can separate the mock services for certain files. For example, my 'api' folder contains 3 files:
api\
index.js // assign all the "modules" and then simply require that.
user.js // all mocking for user
product.js // all mocking for product
file user.js
var user = function(req, res, next) {
if (req.method === 'POST' && req.url.indexOf('/user') === 0) {
res.end(
JSON.stringify({
'id' : '5463c277-87c4-4f1d-8f95-7d895304de12',
'role' : 'admin'
})
);
}
else {
next();
}
}
module.exports = user;
file product.js
var product = function(req, res, next) {
if (req.method === 'POST' && req.url.indexOf('/product') === 0) {
res.end(
JSON.stringify({
'id' : '5463c277-87c4-4f1d-8f95-7d895304de12',
'name' : 'test',
'category': 'test'
})
);
}
else {
next();
}
}
module.exports = product;
index.js just assigns all the "modules" and we simply require that.
module.exports = {
product: require('./product.js'),
user: require('./user.js')
};
My Gruntfile.js file
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app),
require('./api').user,
require('./api').product,
];
}
}
}

Common place to load requirejs config

I am making a hybrid application with SPA and Mvc 3. Now what i require is to load different pages with condition configs in backbone .
I have loaded my main file with like this
require
paths:
jquery:'Libs/jquery/jquery-1.8.0.min'
underscore:'Libs/Underscore/underscore.min'
backbone:'Libs/Backbone/backbone-min'
text:'Libs/Requirejs/text'
bootstrap:'Libs/Bootstrap/bootstrap.min'
jqValidation:'Libs/jquery/jquery.validate.min'
jqValUnobtrusive : 'Libs/jquery/jquery.validate.unobtrusive.min'
shim:
'underscore':
exports : '_'
'backbone':
deps: ["underscore"]
exports:'Backbone'
'bootstrap':
deps : ['jquery']
exports : 'jquery'
'jqValidation':
deps : ['jquery']
exports: 'jQuery.fn.validate'
'jqValUnobtrusive':
deps: ['jquery', 'jqValidation']
exports: 'jQuery.fn.validate.unobtrusive'
require ["App/app","backbone",'bootstrap'] ,(App,Backbone)->
app = new App()
Backbone.history.start()
Now this same set of config is required in other files also . Now how to load this config in each and every main.coffee file where I require ? I dont want this config to be redundant . Just one place I want to put it and then call it to other places . How to do that ?
Loading your require config from a single shared module is a very good plan.
This is the method I use. Different pages and my build system all use the same config file.
The tradeoff is you have to nest your require dependencies, but it's been worth for me.
Index.html, or any other page
<script>
require(['require_config'], function () {
require(['core'], function (core) {
window._app = core.start();
});
})
</script>
require_config.coffee
define [], () ->
require.config
packages: [
'core'
'dashboard/widgets/base'
]
paths:
# 3rd Party Bower Libraries
handlebars: "bower_components/require-handlebars-plugin/Handlebars"
underscore: "bower_components/underscore-amd/underscore"
jqueryui: "bower_components/jquery-ui/jqueryui"
shim:
bootstrap:
deps: [ 'jquery' ]
exports: 'jquery'
markdown:
exports: 'markdown'