AngularJS libraries conflicting with each other - angularjs

I'm using gulp to combine my scripts in order to load only one file in HTML (make it faster).
Here's a sample code, name of libraries don't matter much, you'll get the idea :
// gulpfile.js
mix.scripts([
'vendor/jquery-2.1.1.min.js',
'vendor/angular.js',
'vendor/slideout.min.js',
'vendor/dirPaginate.js',
'vendor/cookie.js'
], 'public/js/libs.js');
And then I do this :
// app.js
let app = angular.module('app', ['angular-slideout', 'cookie', 'dir-paginate'], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
});
export default app;
I only use one file to load every NG library in my project, and then I import this app in my controllers. Now this is only an example, but I already have conflicts depending on the order of mixing these scripts in.
Any advice on processing this ? I already had to ditch some libs I wanted to use because they were conflicting with others. Going on this way, this looks like a dead end.

Related

How to make a webworker use the same typescript code as the app?

My reactjs app consists of a bunch of typescript files with a clean separation of GUI and model. The webworker needs most of model files, so maybe half of all files. I could imagine loading the webworker from exactly the same URL as the app as the model does reference neither the GUI nor React nor other unavailable stuff (At least, it shouldn't, and if so, it'd easy to clean it up).
There seem to be some problems:
finding the correct javascript files
injecting proper start up code into them
and probably others I haven't thought about yet.
The communication to the webworker is not a problem as all I need is a single async call passing and receiving some simple data.
There may be more issues like e.g., https://github.com/microsoft/TypeScript/issues/20595.
Before I learnt what I really need, I tried e.g., ttps://www.npmjs.com/package/#koale/useworker, which is nice, but seems to be able to deal with plain javascript dependencies only.
Finding the correct javascript files
What I can see in index.html is
<script src="/myapp/static/js/bundle.js"></script>
<script src="/myapp/static/js/0.chunk.js"></script>
<script src="/myapp/static/js/main.chunk.js"></script>
<script src="/myapp/main.4e45e2b4b645351b7733.hot-update.js"></script>
I guess, I could live without hot updates, however the names of the other three files change in production to something like "/myapp/static/js/2.28cf00cf.chunk.js".
Injecting proper start up code into them
When the worker loads, it executes some webpack code generated code which most probably crashes it. I'd need to avoid it somehow.
The questions
Is this doable at all?
Does it make sense or is there a better approach?
For a seamless integration of worker code with main-thread code, I recommend using comlink-loader. For example, if you have a main.ts file and a thingy.worker.ts file, you could seamlessly load it as a worker by using TS imports:
// main.ts
import { getThing } from "./thingy.worker.ts"; // make sure the file name ends with .worker.ts
async function test() {
console.log(`the thingy is: ${await getThing()}`);
}
// thingy.worker.ts
export async function getThing() {
return 3;
}
You'll need to add it to your webpack config like this:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.worker\.(js|ts)$/i,
use: [{
loader: 'comlink-loader',
options: {
singleton: true
}
}]
}
]
}
}
The best part is that your editor's intellisense will work across modules and type safety will not be compromised. More documentation is available here.
You need to compile a separate js file for your WebWorker. There is a React lib called react-webworker that makes this easier for you. It in turn uses WebPack’s worker-plugin.

Import angularjs modules with webpack

We've got a rather large project written in angularjs and are moving gradually to angular 4. The plan is to first rewrite everything to typescript + angularjs components. We've set up an empty angularjs+webpack+typescript project and are converting legacy angularjs modules to typescript. This works fine, but because of the size of the project we would like to add the 'old' angularjs modules for now and execute those scripts so we have a full working project.
I haven't found a way to make this work. So basically we've got (I've omitted some details for brevity):
app.module.ts:
import * as angular from 'angular';
import { moduleName as module1 } from './app/converted.module1';
import { moduleName as module1 } from './app/converted.module2';
export const moduleName =
angular.module('application', [
module1,
module2,
'legacy_module_3',
'legacy_module_4'
]).name;
So module1 and module2 are already converted typescript modules. Module 3 and module 4 not. We don't want to convert those yet but do want to reference them. Lets say those modules reside in '/frontend/module3.js' and '/frontend/module4.js', how would I make this work (executed js code) with webpack?
Consider just biting the bullet and doing minimal conversion on everything in one go.
I just went through a similar exercise converting an existing angularjs project to use webpack. The conversion needed for each module is small enough that I just converted all of the modules. So where we had:
angular.module('somemodule').controller(function(){ ... })
I changed those to:
export default function SomeController() { ... }
and the module declaration files all now look like:
import SomeController from './some.controller'
export default angular.module('SomeModule', [])
.controller(SomeController)
.name;
Then the top level:
import SomeModule from './some/module'
angular.module('app', [ SomeModule ]);
It took a little while, but as the changes are largely mechanical I was able to just work systematically through the entire application. Some sub-folders were just using the 'app' module name, so I added a 'module.js' file in each folder with an appropriate module name, but otherwise there weren't any real changes to be made.
I also had to change all of the template urls into imports and I imported the '.scss' file into the top level of the app (though that wasn't really required).
Next step will be to convert controllers and directives to components, but that should be pretty straightforward now.
You've got to export each one of your modules and then import them in your app module. Notice the following example:
//..import your other ts modules
import module3 from './frontend/module3.js' //This have to be relative path
import module4 from './frontend/module4.js'
export const moduleName =
angular.module('application', [
module1,
module2,
module3.name ,
module4.name
]).name;
Also notice that your old js modules should export a module:
e.g. filters module.
import angular from 'angular';
import myNiceFilter from './myNiceFilter.filter';
var filters = angular.module('filters',[]);
filters.filter('myNiceFilter', myNiceFilter);
export default filters;

Require.js fails when including socket.io [duplicate]

I'm getting this error when I browse my webapp for the first time (usually in a browser with disabled cache).
Error: Mismatched anonymous define() module: function (require) {
HTML:
<html>
.
.
.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script> var require = { urlArgs: "v=0.4.1.32" }; </script>
<script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
<script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
</body>
</html>
JS:
$(function () {
define(function (require) {
// do something
});
});
Anyone know exactly what this error means and why its happening?
source file, a short discussion about it in the github issues page
Like AlienWebguy said, per the docs, require.js can blow up if
You have an anonymous define ("modules that call define() with no string ID") in its own script tag (I assume actually they mean anywhere in global scope)
You have modules that have conflicting names
You use loader plugins or anonymous modules but don't use require.js's optimizer to bundle them
I had this problem while including bundles built with browserify alongside require.js modules. The solution was to either:
A. load the non-require.js standalone bundles in script tags before require.js is loaded, or
B. load them using require.js (instead of a script tag)
In getting started with require.js I ran into the issue and as a beginner the docs may as well been written in greek.
The issue I ran into was that most of the beginner examples use "anonymous defines" when you should be using a "string id".
anonymous defines
define(function() {
return { helloWorld: function() { console.log('hello world!') } };
})
define(function() {
return { helloWorld2: function() { console.log('hello world again!') } };
})
define with string id
define('moduleOne',function() {
return { helloWorld: function() { console.log('hello world!') } };
})
define('moduleTwo', function() {
return { helloWorld2: function() { console.log('hello world again!') } };
})
When you use define with a string id then you will avoid this error when you try to use the modules like so:
require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
moduleOne.helloWorld();
moduleTwo.helloWorld2();
});
I had this error because I included the requirejs file along with other librairies included directly in a script tag. Those librairies (like lodash) used a define function that was conflicting with require's define. The requirejs file was loading asynchronously so I suspect that the require's define was defined after the other libraries define, hence the conflict.
To get rid of the error, include all your other js files by using requirejs.
Per the docs:
If you manually code a script tag in HTML to load a script with an
anonymous define() call, this error can occur.
Also seen if you
manually code a script tag in HTML to load a script that has a few
named modules, but then try to load an anonymous module that ends up
having the same name as one of the named modules in the script loaded
by the manually coded script tag.
Finally, if you use the loader
plugins or anonymous modules (modules that call define() with no
string ID) but do not use the RequireJS optimizer to combine files
together, this error can occur. The optimizer knows how to name
anonymous modules correctly so that they can be combined with other
modules in an optimized file.
To avoid the error:
Be sure to load all scripts that call define() via the RequireJS API.
Do not manually code script tags in HTML to load scripts that have
define() calls in them.
If you manually code an HTML script tag, be
sure it only includes named modules, and that an anonymous module that
will have the same name as one of the modules in that file is not
loaded.
If the problem is the use of loader plugins or anonymous
modules but the RequireJS optimizer is not used for file bundling, use
the RequireJS optimizer.
The existing answers explain the problem well but if including your script files using or before requireJS is not an easy option due to legacy code a slightly hacky workaround is to remove require from the window scope before your script tag and then reinstate it afterwords. In our project this is wrapped behind a server-side function call but effectively the browser sees the following:
<script>
window.__define = window.define;
window.__require = window.require;
window.define = undefined;
window.require = undefined;
</script>
<script src="your-script-file.js"></script>
<script>
window.define = window.__define;
window.require = window.__require;
window.__define = undefined;
window.__require = undefined;
</script>
Not the neatest but seems to work and has saved a lot of refractoring.
Be aware that some browser extensions can add code to the pages.
In my case I had an "Emmet in all textareas" plugin that messed up with my requireJs.
Make sure that no extra code is beign added to your document by inspecting it in the browser.
Or you can use this approach.
Add require.js in your code base
then load your script through that code
<script data-main="js/app.js" src="js/require.js"></script>
What it will do it will load your script after loading require.js.
I was also seeing the same error on browser console for a project based out of require.js. As stated under MISMATCHED ANONYMOUS DEFINE() MODULES at https://requirejs.org/docs/errors.html, this error has multiple causes, the interesting one in my case being: If the problem is the use of loader plugins or anonymous modules but the RequireJS optimizer is not used for file bundling, use the RequireJS optimizer. As it turns out, Google Closure compiler was getting used to merge/minify the Javascript code during build. Solution was to remove the Google closure compiler, and instead use require.js's optimizer (r.js) to merge the js files.

#section syntax instead of requirejs or browserify for angularjs application

I understand that requirejs and browserify can load my files dependent on its current context, and that it is amazing. I would really prefer to use the #section sections syntax that the razor engine uses. Was just wondering if there is a way to implement this into a typescript / angularjs application.
for example
index.html
#renderSection scripts;
// which could turn into something like
<script data-render="scripts"></scripts>
// the app.run() could declare all the scripts that will be needed on every
// page view
view.html
<script ng-section-repeat="injected in injection"></script>
// the ng-section-repeat is basically taking all the items in the
// typescript constructor and then finding out which ones are needed for
// that view.
I like the idea injecting application file dependencies in the view , without a configuration file and all the added extras that comes with the loaders.
I just want to easily define what files are needed in the actual view and get them loaded, with angular's dependency injection handling the dependency itself.
If you are handling all your dependencies with $inject then , as far as i can tell, dependency is technically already setup in the controllers, all one would need, is to load this as it is called. Which could even eliminate the need for the #section scripts completely
Update:
What i have done to sort of replicate the module loaders is to just use gulp-concat and define the file order in my gulp.config.js and then pass it to the gulp-src before running $.concat .this allows me to have the files in the gulp steam , in dependent order . They are however loaded on the first load. With gulp-uglify the files are tiny ( its now at 566Kb with 16 external libraries loading in 69ms . To put that into perspective it takes 209ms to load one google font ).
I dont know maybe i am not understanding browserify correctly but i honestly struggle to see the need for it, its seems extremely convoluted for something so simple
It is possible using external modules and an injector to do what you asked for:
I just want to easily define what files are needed in the actual view
import {UserFactory} from 'models/userFactory';
import {UserValidator} from 'models/userValidator';
import {Inject} from 'angular2/di';
and get them loaded, with angular's dependency injection handling the dependency itself.
Note: My example uses angular 2.x because I less familiar with angular 1.x and I'm sure you can do something really similar...
class SomeComponent {
userName: string;
userRating: number;
rating: number;
constructor(
#Inject(UserFactory) UserFactory
#Inject(UserValidator) UserValidator
)
{
this.UserFactory = UserFactory;
this.UserValidator = UserValidator;
}
}
Then you can use Browserify to create a bundle.js file that can be executed in a web browser.

Grunt-Karma-Jasmine: can not find module

I am trying to set up tests for my Angular.js project and I keep getting "$injector:nomod, Module 'result' is not available! You either misspelled..." error. I am sure that I am including "result" module in the "files" array inside "karma.config.js", basically it looks like this:
files: [
'../javascripts/jquery-2.1.4.min.js',
'../jquery-ui/jquery-ui.min.js',
'../D3/d3.js',
'libs/angular.min.js',
'libs/angular-route.min.js',
'libs/angular-animate.min.js',
'libs/selectize.js',
'libs/angular-selectize.js',
'libs/angular-mocks.js',
'simulator.js',
'*.js',
'services/**/*.js',
'qa/tests-*.js'
],
...
I thought initially that the ordering of the main module: 'simulator' (defined inside 'simulator.js' file) is wrong, so I specifically moved it upwards, before
the other modules, like the following stackoverflow thread recommends:
Angular module not available in Karma Jasmine test run
It did not help. Then I tried to make sure that the files are imported in the same order as in my angular apps' main entry file (except for angular-mocks.js and qa/tests-*.js), importing each single file, instead of using wildcards, but no success.
Jasmine definitely goes inside the test files but stumbles upon the line where I am trying to import the module "result":
describe('simulator.chartService', function() {
var chartService;
var graphConfig;
console.log("instantiating module result");
beforeEach(module('result'));
console.log("finished instantiating");
beforeEach(inject(function($injector) {
graphConfig = $injector.get('graphConfig');
chartService = $injector.get('chartService');
}));
it('should be created', function() {
expect(chartService.calcColors(10)).not.toBeNull();
});
});
So, I see that the error happens in-between two console.log() statements.
I suspect that still something can be wrong with the ordering of my files inside the array "files" in "karma.config.js". I have main module "simulator" which is dependent on other modules:
angular.module('simulator', ['ngRoute','ngAnimate','selectize','newexp2','newexp','login','edit','exps', 'result','templates','commons'])
Modules 'newexp2', 'newexp', 'login', 'edit', 'exps', 'result', 'templates' are all dependent on the module 'commons'.
How to correctly import interdependent modules inside the "files" array?
Is it just enough to place "simulator.js", main module, above all others,
or I also need to place all other modules before "commons.js"?
Another my suspicion is that angular.js library version that I downloaded from the official angular website, "angular-mocks.js", can be incompatible with other modules that I am using. I had such an issue with "angular-animate.js" file before.
As long as I surround my test code with $(function(){...}) (and all other my modules ARE surrounded with it) it does not generate the error while importing the result module, so I start seeing two console.log() statements without an error in-between, however, this generates some unknown error which prevents me from invoking the it part at all, whereas when I do not surround it with $(function(){...}), the it test is invoked, but the module result import fails.
So far I am pretty much stuck and do not know where to move and what to try. Any suggestion would be greatly appreciated.
OK, I figured it out. The issue was that ALL of my angular code was enclosed inside $(function(){...}). The solution is to remove all of the $function(){...}), then reorder javascript imports inside the main entry .html file, and then all of the testing starts working good.
The question might be better to mark as duplicate with:
Angular document.ready() issue

Resources