I'm using RequireJS to load my JavaScript modules for a BackboneJS web app, but I'm running into a style issue at the moment.
I have two classes that share a LOT of code, but they both subclass different classes.
TemplateLessonView LessonView
| |
| |
EditorApp <-- these share code --> MainApp
Now to keep things DRY I'd like MainApp to extend EditorApp, but then EditorApp's dependencies are loaded and EditorApp calls some of it's base class' functions by means of this format: this.constructor.__super__.initialize.apply(this);
A solution would be to change EditorApp's dependencies when the module is loaded from MainApp's module (so I would require LessonView but pass it to EditorApp as TemplateLessonView.
Does anyone know of a way to do this, or has another suggestion to accomplish what I'm trying here?
On way to solve this is to create a module that you will import in both class definition...
something like that :
(...require stuff ...)
return {
myfct1 : function(){
},
myfct2 : function(){
}
}
and then you can import the module where you need it, and then call your common code like a library...
Related
I am totally new to webpack (i previously built my apps by including tons of css / js files by "hand") and am now trying to understand how namespaces work when working with the named tools.
i have an app.js
require('./bootstrap');
require('./helperFunctions');
/* ... more, unrelated stuff */
webpack.mix.js is untouched from the original file delivered with the laravel 5.5 sample project
let mix = require('laravel-mix');
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
my helperFunctions.js is a simple js file with some helpful functions i want to use throughout my project:
function foo_bar(A, B) {
return A - B;
}
/* more functions, following the same structure... */
but everytime i try to use one of the functions defined in the helperFunctions file i find that they are "undefined", even in the app.js file directly after the 'require' happens.
after inspecting the generated app.js file i found that my functions are encapsulated in an anonymous function function(module, exports) { /* my File contents go here */ }, resulting in them being unavailable to the rest of the scripts.
while i understand that this is propably there to reduce polluting the global namespace, i dont understand how i am supposed to define global objects (such as data Storage objects for vue) or functions such as helper functions.
can anybody explain how this is supposed to work, or link me to a ressource explaining this for someone who never worked with an asset compiler (if this is even the right terminus).
cheers
// Edit: i think i found a solution, after stumbling over this:
https://nodejs.org/api/modules.html#modules_modules
I editted the helper functions file to something like this:
module.exports = {
foo_bar(A, B) {
return (A - B);
},
/* ... more functions ... */
}
And imported it wherever i need it like this:
import HelperFunctions from './helperFunctions'
var result = HelperFunctions.foo_bar(5, 8);
However, this only works in files which are pre packed using webpack. is registering the component under window.HelperFunctions the only way to make them available in dynamically generated <script></script> tags throughout the website?
Registering your helper methods on the window object, as you kind of suggested, is a simple and easy to understand approach, so that's what I would choose to do if I wanted these methods to be available globally.
window.myHelperMethod = function () { console.log('ayo, this works!') }
I'm trying to create a Base Class for my controllers, so I can avoid duplication of code.
The problem here is that it is throwing me errors whenever I try to use it.
"Assertion Failed: You attempted to define a {{link-to "inventory"}} but did not pass the parameters required for generating its dynamic segments. Could not find module controllers/base-inventory imported from frontend/controllers/inventory"
To create my base controller I am using ember cli and this is what I did:
ember g controller base-inventory
Then
// base-inventory.js
const BaseInventory = Ember.Controller.extend({
//my code...
});
export default BaseInventory;
In the controller where I want to use this base class I did the following
import BaseInventory from 'controllers/base-inventory';
// also tried import { BaseInventory } from 'controllers/base-inventory';
// and export default new BaseInventory({});
export default BaseInventory.extend({
//more code here...
});
Any thoughts of what I am doing wrong?
I didn't plan to use mixins, because it doesn't seem the best option here at first. I am not really sure about the sharing content, which mixins provide. I don't think it would be a problem since I'm trying to inherit within controllers, but as I said I'm not sure about how it really works.
If it's not possible to do the way I'm trying to, I'll write a mixin.
Both files are in the same folder structure so import path should be like ./base-inventory
import BaseInventory from './base-inventory';
I've built a lot of APIs and applications using ES2015, but I am not used to the best practices in TypeScript yet, so maybe you can help me.
Let's say I am building an API/SDK for a shop. The goal is that the user includes my js file and accesses the shop and its namespaces via the window object, much like it is possible with angular and other libs as well.
window.shop.init();
window.shop.cart.get();
window.shop.cart.set();
window.shop.cart.clear();
In ECMAScript 2015, I would write my methods like get and set, import them in my main file and extend the shop object and finally the global object.
// in my cart.js namespace file
export {get} from './get';
// in my shop.js
import * as cart from './cart';
global.shop = {
cart
}
Being a good approach for namespacing in ES2015, it feels kinda wrong in TypeScript having all those module and namespace keywords.
I basically want to achieve the same in TS. I tried things like the following, but with no success.
module shop {
export const cart = {...}
}
(<any>window).shop = shop;
or
namespace shop {
// ...
}
(<any>window).shop = shop;
There where some tutorials claiming that a module is automatically attached to the global/window object, but that did not happen for me.
I am using TypeScript 1.8.10. Any help is greatly appreciated!
There where some tutorials claiming that a module is automatically attached to the global/window object, but that did not happen for me.
Maybe because the code of your namespace is in an (ES6) module instead of in a script? The differences between scripts and modules are detailed here.
The code below makes a global variable shop in the browser if it is loaded as a script, ie with a tag <script src="shop.js"> (or you can concatenate this file with other JavaScript files, for example with uglifyjs).
// File shop.ts
namespace shop {
export const cart = { /* ... */ }
}
If your code is loaded as an ES6 module (ie with the help of Webpack, SystemJS, RequireJS or other), your solution is valid:
(<any>window).shop = shop;
The answer by #paleo is not perfect.
It just suppress the type inference for shop.
I also encounter the similar problem this morning. I tried so many "solutions" on SO, but none of them produce no type error absolutely and enable triggering type jumping in IDE(webstorm or vscode).
Finally, from here
https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512
, I find a reasonable solution to attach typings for global variable which acts as interface/class and namespace both.
Example is below:
// typings.d.ts
declare interface Window {
shop?: MyNamespace & typeof MyNamespace
}
declare interface MyNamespace {
somemethod?()
}
declare namespace MyNamespace {
// ...
}
Now, the code above merges the typings of namespace MyNamespace and interface MyNamespace into the global variable shop(the property of window).
Given the following simplified scenario, how could I best construct my reusable component so that it is correctly consumable by another application, such that foo.js prints 23?
Reusable Component:
/home.js
/main.js
/stuff
foo.js
--
/home.js:
define([], function () { return 23; }
/stuff/foo.js:
define(['home'], function (home) { console.log(home); } // prints 23
Consumer Application:
/app.js
/main.js
/home.js
/views
template.html
/bower_components
/myReusableComponent
/home.js
/main.js
/stuff
foo.js
--
/home.js:
define([], function () { return 17; }
/bower_components/myReusableComponent/home.js:
define([], function () { return 23; }
/bower_components/myReusableComponent/stuff/foo.js:
define(['home'], function (home) { console.log(home); } // now prints 17
Is there a consumer application requirejs config that sets the baseUrl of any module in /myReusableComponent to '/myReusableComponent'? My reusable component should not have/need access to the root level of the consumer application anyway.
I have looked into the r.js optimizer, but it just outputs a bunch of define('stuff/foo', [], function ())... what happens if the consumer application has a stuff/foo.js too?
The only solution I have found so far is forcing the use of relative paths in all of my modules: define(['../home'], function (home) { console.log(home); } but I am hoping there is a more elegant way to solve this problem.
All feedback is very appreciated!
If you want to produce a library that is going to be usable in different applications, then you should use use relative paths when one module of your library refers to another, because this makes it more likely that whoever uses your library will be able to do so without having to do modify their RequireJS configuration.
Some clashes can be eliminated by the judicious use of map or paths. Ultimately, however, there are cases that cannot be solved (or at least not be solved as the user wants it) without having access to the unoptimized modules so you should distribute your library as an optimized bundle and provide the possibility to load it as a collection of unoptimized modules.
When working with lots of classes in a node module is the following mechanism a good idea or is there a better way to achieve this?
// mymodule/core.js
module.exports = {
ClassA: require('./class/ClassA'),
ClassB: require('./class/ClassB'),
ClassC: require('./class/ClassC')
}
// mymodule/class/ClassA.js
module.exports = function() {
...
}
// myapp.js
var core = require('mymodule/core')
;
var a = new core.ClassA();
The idea of the above is to keep classes in physically separate modules for maintenance whilst providing a namespace that is easy to use.
For me it is far clearer to have the modules you are using pulled in within the module using them. You can't get around the fact that the module has these dependencies and it will be easier for someone else reading the code to see what is being used.
Also if you ever wanted to reuse a single module you would have to also carry with it the core.js module–and all of it's dependencies–from which your module is coupled.