How to import ES6 modules in ExtjS 6/7 - extjs

I haven't found anything related to this topic.
I'd like to import pusher like normally is done with other js frameoworks:
npm install pusher-js
Then you just import the library:
import Pusher from 'pusher-js';
or
const Pusher = require('pusher-js');
Please share good practices to accomplish that in an ExtJS application.
The last resort would be to just include the min file in app.json:
...
"js": [
{
"path": "https://js.pusher.com/7.0/pusher.min.js",
"bundle": true,
"compress": false
}
], ...
Or even worse, put the include in the index.html file:
<script src="https://js.pusher.com/7.0/pusher.min.js"></script>
Any ideas?
Thanks.

if including it using app.json is not what you want you can load it at the time you need it.
Async (onLoad, onError are the promise)
Ext.Loader.loadScript({
url: 'pusher-js',
onLoad: successFn,
onError: errorFn,
scope: this
});
Sync (the code will continue, after the file has been loaded)
Ext.Loader.loadScriptsSync(url|[url]);
Optional Approach
If you add Ext.require ExtJS will try to load the file and you can use this in your controller.
Ext.define('MyApp.view.SomeViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.someview',
init() {
// Preload additional functionality
Ext.require('MyApp.libs.pusher-js');
// from folder ===> MyApp/app/libs/pusher-js
}
})
OR
Read this as a starting point.
Using app.json you can get it all prepared as:
"js": [
{
"path": "https://js.pusher.com/7.0/pusher.min.js",
"remote": true
}
],
...
Inside your initialization:
var pusher = new Pusher('APP_KEY', {
cluster: 'APP_CLUSTER'
});
This will load the file automatically and you do not have to import it in any way.

Related

Requirejs callback undefined on code splitting

I'm a newbie to RequireJS I have a ReactJS app with index.jsx as an entry point
// index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
export function callBackForRequirejs() {
return "testing";
}
When I load my build via RequireJS I get these callbacks
require(["/path/to/bundle"], function(callback) {
console.log(callback) // I get "callBackForRequirejs"
}, function(err){
console.log(err)
});
But when I do code splitting I'm getting undefined in the callback, for code splitting I'm using these configs
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: "vendor",
chunks: "initial",
}
}
}
}
UPDATE:
Actually, my react app is a plugin for some external app, the external app loads my plugin via RequireJS. The code inside an external app is something like this
case 1:
require(['/pathof/my/react/plugin/bundle.js'],
function(callbackwhenpluginloads){
callbackwhenpluginloads()
})
Since the size of my bundle.js is very large so I decided to split it into two parts one which comes from node_modules and one from my code
Now the external plugin loads my react plugin something like this
case 2:
require(['/pathof/my/react/plugin/bundle.js',
'/pathof/my/react/plugin/vendor.js' ], function(callbackwhenpluginloads){
callbackwhenpluginloads() // callbackwhenpluginloads is undefined
})
I'm getting undefined callback when the external app loads my plugin in
Actually, based on RequireJS docs for starting you did the following way and it works well:
require(['/path/to/bundle.js'], function(callback) {
console.log(callback) // you get callbackForRequireJS
}, function(error) {
console.log(error)
});
And now you did a code-splitting on your project, so you should consider this the vendor.js is like a dependency to split bundle.js file. so you should follow this example to load the dependencies at the first and then run the other split code. so your code is something like below:
requirejs.config({
paths: {
reactApp: 'path/to/bundle.js'
},
deps: ['path/to/vendor.js'],
});
require(['reactApp'], function(callback) {
console.log(callback) // it should works now
}, function(error) {
console.log(error)
});
Or there is another way that I don't recommend it:
require(['path/to/vendor.js'], function() {
require(['path/to/bundle.js'], function(callback) {
console.log(callback) // it should works now
}, function(bundleError) {
console.log('bundleError', bundleError)
});
}, function(vendorError) {
console.log('vendorError', vendorError)
});
It seems, for code splitting you are using the webpack. webpack and require js don't really get along.
you should try vanilla JS instead.
<script onload="handleOnLoad()" />
Or go for a npm package.
react-load-script - npm

AngularJs Multiple Times loaded

I have a problem with upgrade my angularJs Application to Webpack4.
this is my setup:
vendor.ts
import "angular";
import "angular-i18n/de-de";
import "angular-route";
and
main.ts
import {MyAppModule} from "./my-app.app";
angular.element(document).ready(() => {
angular.bootstrap(document.body, [MyAppModule.name], { strictDi: true });
});
With webpack 3. I had a commonsChunkPlugin and everything worked.
With webpack 4, I'm using the splitChunks option to not import angularjs 5 times:
webpack.config.ts
...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: "commons",
chunks: "initial",
minChunks: 2
}
}
}
}
...
That is working correctly. I have loaded the angularjs code only in my common.js file. But unfortunatelly the code is instantiated twice, so the app always logs the warning:
WARNING: Tried to load AngularJS more than once.
The chunks are loaded via HtmlWebpackPlugin in the html.
Any idea how to remove the warning?
Found the solution in the deeps of github issues:
The vendor file should not be an entry point but the entry point should be a list of files:
...
entry: {
main: ['./vendor.js', './main.js']
},
...

How angular-translate-loader for webpack works?

I'm trying to integrate the webpack loader: angular-translate-loader to my project.
The documentation lacks a full example and I can't figure out how to make everything works together.
What I want:
Have a "languages" folder at the same level of my root component that will contain the locales for other languages like:
locale-fr.json
locale-sp.json
What I tried:
I added this in my webpack.config.js (as per documentation)
module.exports = {
module: {
preLoaders: [{
test: /\.json$/,
loader: 'json'
}],
loaders: [{
test: /\.json$/,
loader: 'angular-translate?module=translations'
}]
},
angularTranslate: {
namespaces: ['app'],
sep: '.',
defaultLocale: 'en'
}
};
And in the root component of my application I got this:
$translateProvider.translations('en', {
TITLE: "Translation is working",
ANOTHER_TEXT: "But is it really working"
})
.translations('fr', localFr)
.registerAvailableLanguageKeys(['en', 'cn', 'fr', 'sp'], {
'gb': 'en',
'es': 'sp'
})
.preferredLanguage('en')
//See http://angular-translate.github.io/docs/#/guide/19_security for more details about Sanitize
.useSanitizeValueStrategy('escape')
//Remember the choice of Language in the local storage
.useLocalStorage();
The default language obviously works (en) but not the others.
I'm missing something but I can't figure out why.
Does someone know of a sample project using angular-translate-loader and webpack ?
I was stuck on the same thing the whole day, but after a lot of trial and error I've finally found a working solution. I have a similiar set-up as you: I have a folder assets/languages at the root of my project, containing languates in JSON files with the format locale-nl.json.
What worked for me was to import angular-translate directly (together with some extra dependencies) instead of using angular-translate-loader:
npm install --save angular-translate angular-sanitize angular-cookies
I then added this to my app.module.js file (which is what I use instead of index.js):
// No "real" module support yet for angular-translate, wo we have to load these manually.
// Reference: https://github.com/angular-translate/angular-translate/issues/1517
import "angular-sanitize";
import "angular-cookies";
import "angular-translate";
import "angular-translate/dist/angular-translate-loader-static-files/angular-translate-loader-static-files.js";
import "angular-translate/dist/angular-translate-storage-cookie/angular-translate-storage-cookie.js";
Then, I define my module and configure the $translate service as follows:
angular.module(MODULE_NAME, [ "pascalprecht.translate", "ngSanitize", "ngCookies" ])
.config(['$translateProvider', function($translateProvider) {
$translateProvider
.useStaticFilesLoader({
prefix: "../assets/languages/locale-",
suffix: ".json"
})
.preferredLanguage('en')
.useCookieStorage()
.useSanitizeValueStrategy('sanitize');
}])
My translation files, e.g. locale-nl.json all contain a single object in this format:
{
"PASSWORD": "Wachtwoord",
"FORGOTPASSWORD": "Wachtwoord vergeten",
"SETTINGS": "Instellingen",
"LOGOUT": "Uitloggen",
"LASTNAME": "Achternaam",
"FIRSTNAME": "Voornaam",
"BIRTHYEAR": "Geboortejaar"
}
Finally, in my HTML code, I call the translations through the $translate directive:
<span translate="SETTINGS">Settings</span>
I don't have time now to create a sample project, but since there were no responses to your question yet I wanted to at least let you what worked for me. I'll see if I have the time to create a sample project this weekend.

r.js cannot resolve dependencies mentioned in shim

I've recently joined a project which is built using Backbonejs, (uses Marionette for view rendering) + nodejs. They also use requirejs to load the backbonejs files. Would like to add at this stage, that I've never worked with backbonejs or requirejs before and hence I'm struggling with the issue I describe later.
Some code that will help explain the issue that I run into (All this code was already written by previous dev's)
Folder Structure:
/public
/js
/collection (consists all Backbone.js collections files)
/lib
/bower_components
/backone
/marionette
/etc
/models (consists all Backbone.js models files)
/views (consists all Backbone.js view files)
/main.js
/main.build.js
/app.js
/controller.js
/router.js
Code from files that I think relate to issue:
main.js
requirejs.config({
paths: {
'async': 'lib/bower_components/requirejs-plugins/src/async',
'jquery': 'lib/bower_components/jquery/dist/jquery.min',
'underscore': 'lib/bower_components/underscore/underscore-min',
'lodash': 'lib/bower_components/lodash/dist/lodash.min',
'backbone': 'lib/bower_components/backbone/backbone',
'marionette': 'lib/bower_components/marionette/lib/backbone.marionette.min',
'markercluster':'lib/markercluster',
'jquerymobile': 'lib/jquery.mobile-1.4.0.min',
'hogan': 'lib/template-2.0.0.min',
'templates': '/templates',
'real': 'lib/mainjs',
'touch': 'lib/jquery.touchSwipe.min',
'mouse': 'lib/jquery.mousewheel',
'moment': 'lib/moment-2.5.1.min',
'humanize': 'lib/bower_components/humanize-plus/public/dist/humanize.min',
'validator': 'lib/bower_components/validator-js/validator.min',
'real': 'lib/mainfile'
},
shim: {
backbone: {
deps: ["underscore"]
},
marionette: {
deps: ["backbone"]
},
templates: {
deps: ["hogan", "jquery"]
},
real: {
deps: ["jquery", "jquerymobile", "touch", "mouse"]
},
markercluster: {
exports: "MarkerClusterer"
},
humanize: {
exports: "humanize"
}
},
waitSeconds: 0
});
define('gmaps', ['async!http://maps.google.com/maps/api/js?v=3&key=AIzaSyBiV8f88yLWJ_IMSdP1fVNO1-gt3eLVSgg&sensor=true&callback=gMapsCallback'], function(){
// define('gmaps', ['http://maps.google.com/maps/api/js?v=3&sensor=false'], function(){
return window.google.maps;
});
require(['app', 'templates', 'real'], function(app) {
app.start({
version: "0.9.9"
});
});
main.build.js
({
baseUrl: ".",
name: "main",
wrapShim: true,
out: "main-built.js"
})
app.js
define(['underscore', 'controller', 'router', 'models/Cache', 'views/RootView'], function(_, Controller, Router, Cache, RootView) {
var Application = Marionette.Application.extend({
propertyListPageSize: 3,
initialize: function() {
_.templateSettings = { interpolate : /\{\{(.+?)\}\}/g };
},
onStart: function(options){
new RootView();
this.controller = new Controller();
this.router = new Router({controller: this.controller});
this.cache = new Cache();
this.context = {};
//this.evHistory = [];//#todo remove once BB/marionette navigation is in place
if(Backbone.history) Backbone.history.start({ pushState: false });
if(Backbone.history.fragment === "") this.navigate('home');
},
navigate: function(fragment, trigger, replace){
this.router.navigate(fragment, {trigger:trigger, replace:replace});
},
back: function() {
window.history.back();
}
});
app = new Application();
return app;
});
rootView.js
define(['marionette', 'views/HomeView', 'views/HeaderView', 'views/FooterView', 'views/MenuView', 'views/VideoView', 'views/LocationSearchView', 'views/LoginView', 'views/FindView', 'views/ServicesView', 'views/ValueView', 'views/PropertyListView', 'views/SideBySideView', 'views/ConfirmRegistrationView', 'views/ForgotPasswordView', 'views/CreateAccountView', 'views/UserHomeView', 'views/MyBrokerView', 'views/GiveFeedbackView', 'views/SeeFeedbackView', 'views/ViewingScheduleView', 'views/MyViewingsSummaryView', 'views/MyAccountView', 'views/ViewingConfirmView', 'views/ValueAddressPropertyListView'],
function(Marionette, HomeView, HeaderView, FooterView, MenuView, VideoView, LocationView, LoginView, FindView, ServicesView, ValueView, PropertyListView, SideBySideView, ConfirmRegistrationView, ForgotPasswordView, CreateAccountView, UserHomeView, MyBrokerView, GiveFeedbackView, SeeFeedbackView, ViewingScheduleView, MyViewingsSummaryView, MyAccountView, ViewingConfirmView, ValueAddressPropertyListView) {
var RootView = Marionette.LayoutView.extend({
...some view code
});
Use case I'm trying to solve:
So when I access the site in the browser, I notice in the debugger that it loads all the js files right at the beginning. During the load process my site is blank and user has to wait a while before he can use the site.
So what I've been able to understand is that when app is 'started' in main.js, app.js creates an instance of rootView.js , which in turn has all the views listed as dependencies. This triggers a download request for all the other views which in turn would solve their own dependencies and download all the relevant models and collections. Hence all files being downloaded when the user accessed the site.
Solution I've been trying:
Since requirejs is being used, I'm trying to use r.js to optimize and combine all the js files to reduce the number of downloads.
Issue I'm running into:
When i run r.js. i get the following error
Tracing dependencies for: main
Error: ENOENT: no such file or directory, open '/var/node_projects/rm/rm.src.server/src/public/js/underscore.js'
In module tree:
main
app
Error: Error: ENOENT: no such file or directory, open '/var/node_projects/rm/rm.src.server/src/public/js/underscore.js'
In module tree:
main
app
at Error (native)
If I add the underscore.js files directly to the specified path in the error, then I get the same error for marionette.js. What I think is happening is that app.js is not recognizing the shim'ed dependencies and hence its trying to find the files directly at specified path in the error.
Things I've tried:
- I've added wrapShim: true in the main.build.js file but that did not help
Honestly, I've been sitting on this for a couple of days and I'm not sure what I can do next and hence this post.
Any help/direction would be appreciated.
You need to include the same shim configuration in your build file, as wrapShim is not sufficient.
If shim config is used in the app during runtime, duplicate the config here. Necessary if shim config is used, so that the shim's dependencies are included in the build. Using "mainConfigFile" is a better way to pass this information though, so that it is only listed in one place. However, if mainConfigFile is not an option, the shim config can be inlined in the build config.
https://github.com/jrburke/r.js/blob/master/build/example.build.js

Ext JS 5.1 won't load use appfolder path to find js

I am trying to clean up and restructure my javascript in my app, but once I change it it stops working. I am using ext scheduler in my app so that might be the problem. Here is how I want to set up
/ext/scheduler-3.0.0(all core code for schedule components go here)
/ext-all.js
/myscheduler(custom code for schedule components go here)
--/global/
----/view/
------globalscheduling.js
/model/
And This is how I start my app
ExtLatest.Loader.setConfig({enabled: true});
ExtLatest.define("scheduler.Application", {
extend: "Ext.app.Application",
requires: ["myscheduler.global.view.globalschedulegrid"],
name: "scheduler",
appFolder: "",
launch: function () {
getData()
}
});
However extjs still trying to go to https://c.na17.visual.force.com/apex/myscheduler/global/view/globalschedulegrid.js to find my view file what I doing wrong here?
Ext.Loader.setPath('myscheduler.global.view.globalschedulegrid', 'path to my scheduler');
OR
Ext.Loader.setConfig({
paths: {
'myscheduler': 'myscheduler',
}
});
Link to 5.0 Doc (Not sure which version you are using but it's the same)
5.1 as noted in the title. I didn't have to set the path for globalschedulegrid. Just specifying the paths in setConfig like this
ExtLatest.Loader.setConfig({enabled: true,
paths: {
'scheduler': "{!URLFOR($Resource.ConnectWeb, 'scripts/libs/scheduler')}"
}
});

Resources