Short version
Would you, as a web app developer, be OK with a gadget or a library that requires some ES5 shims like these for it to work in IE7&8? How about if it included these shims itself, thus patching your global JavaScript?
Long version
When writing an open source node module that is meant to be run also in old browsers like IE7 and IE8, where should I "get" my ES5 Array.prototype.forEach, Object.keys and such?
Should I rely on environment–patching shims (like like https://github.com/es-shims/es5-shim) or non–environment–patching shims (like https://www.npmjs.org/package/lodash.keys)?
The original issue is this.
I supplied my own answer to this but it is inconclusive. I would like to ask:
What is the standard for this? Is there a common policy?
Are there performance implications that are meaningful?
What other upsides and downsides have I not included in my answer?
Are there module maintenance considerations I have not taken into account?
Environment–patching shims
Shims like https://github.com/es-shims/es5-shim "monkey-patch a JavaScript context to contain all EcmaScript 5 methods that can be faithfully emulated with a legacy JavaScript engine", thus allowing me to write my module with some of the ES5 methods.
Downsides
My module code is simpler ([1, 2, 3].forEach(function(){});).
Upsides
I must include shims in my testing setup, if I'm testing in those browsers that need them.
I "force" my module's consumers to rely on shims.
Non–environment–patching shims"
Or, "non–shims" like lodash.keys or foreach, can be used.
Upsides
I don't need to use shims in my tests.
I don't "force" my module's consumers to use shims.
Downsides
My module's code is less pretty, like
var forEach = require("foreach");
forEach([1, 2, 3], function(){});
And I can't use as a method, which negates possibility of chaining.
Related
I'm trying to write a new language detector plugin for i18next for integration with hapi. There's an existing hapi-i18next plugin that is quite old (it uses an extemely old version of i18next, 1.7.10 ) and so mostly useless. And the i18next API docs are pretty vague about how to write new plugins and exactly what the language detection process is. Does it run every time the t() function runs? should it be asynchronous? Has anybody else out there recently integrated hapi with i18next? I realize this is rather general but i'm not sure where else to turn.
Never used hapi so far, but seems hapi evolved a lot since version 8 (what's actually used here)
I don't know if that project is still maintained...
Perhaps you could try to create a new hapi-i18next plugin... (was not that much code)
To create a languageDetector plugin, it should not be a big thing... start here and continue by comparing how the express language detection works
In i18next the languageDetector is triggered here
...so on init/load and on a potential language change
I hope this helps.
What I ended up doing is writing a hapi server extension rather than a plugin, and a module that runs at startup that decorates the hapi server object with the initialized i18next object. The extension is installed to run onPreHandler and it basically clones the i18next object, attaches that instance to the request object, and detects the language (from the request header or from a query parameter), then sets the cloned instance to that language. This way, whenever a route handler uses the t() function attached to the instance that's attached to the current request, we know we'll be translating into the right language. Note that this is still for Hapi 16 (I need to port to 17/18 soon)...
I'm using pouchdb as a library in a tiddlywiky project. It provides a common js compatible environment, so I can just require it.
My project is targeted to several browsers so I can't expect promises to be available as default. Since pouchdb uses promises extensively I tough that it will be simpler to use promises in the rest of my code. I know that pouch includes a promise polifil, so here is my question :
Is that polifil available from outside? Can I use it? How?
Thanks and regards
Yes, you can use PouchDB's promise polyfill by using pouchdb-promise: https://www.npmjs.com/package/pouchdb-promise
If you are using npm, then it's just require('pouchdb-promise'). Otherwise, you can get it from wzrd.in: https://wzrd.in/standalone/pouchdb-promise
As I'm writing a Firefox XUL Extension I find that I want to share some functionality (the business logic) across the whole extension. What would be the best place to store this?
Can I create some sort of library (javascript) file which always gets loaded first?
You most likely want to create a JavaScript code module. You can use Components.utils.import() to load it:
Components.utils.import("chrome://myaddon/content/utils.jsm");
And in utils.jsm you define which symbols should be imported by that statement, e.g.:
var EXPORTED_SYMBOLS = ["Utils"];
var Utils = {
};
The module will be loaded when it is first used and stay in memory after that - there will be only a single module instance no matter how many places on your extension use it. Note that I used a chrome:// URL to load the module, this is supported starting with Firefox 4. Documentation recommends using resource:// URLs which is cleaner because modules don't actually have anything to do with the user interface - still, using a chrome:// URL is often simpler.
I would like to be able to build functionality for my application in a plugin style system for a couple reasons:
New projects can choose which plugins are necessary and not have code for functionality that's not needed
Other developers can build plugins for the system without needing too much knowledge of the core workings.
I'm not really sure how to go about implementing this. I would like to have a plugins folder to host these separately but I guess my questions are:
How do plugins interact with the core system?
How does the folder structure work? Would each hold the standard MVC structure: controllers, services, models, views, etc?
I guess if anyone has a tutorial or some documentation relating to this technique that would be helpful. I've done a bit of searching but it's all a little too closely related to the actual code they're working with instead of the concept and I hadn't found anything specifically related to nodejs.
I suggest an approach similar to what I've done on the uptime project (https://github.com/fzaninotto/uptime/blob/master/app.js#L46):
trigger application events in critical parts of your application
add a 'plugins' section in the applicaition configuration
each plugin name must be a package name. The plugin packages should return either a callback, or an object with an init() function.
either way, inject to the plugins the objects they will need to run (configuration, connections, etc) when calling init(), or executing the callback.
plugin modules register listeners to the application events and modify it
Benefits:
lightweight
rely on npm for dependencies
don't reivent the wheel
Create a plugin prototype for the base
functionality, and let the user define its plugin in a module. In the
module the user would inherit an object from the prototype, extend its
functionality, and then export a constructor which returns the plugin
object.
The main system loads all plugins by require("pluginname") and for
each calls the constructor.
I was hoping to make a Rails app usable both as an Engine and as a standalone Application.
Specifically, I have a nascent app which I'd like to plug in to a customer's site, but ideally, I'd like to just as easily use the app as a standalone system. However, if config/environments/*.rb exist in the enginified version of my app, I get an Uninitialized Constant error at the time the app that I'm having take a dependency on my engine starts up; Rails complains that the MyEngineModule::Application constant can't be found in development.rb, which I think is simply a load order issue, since this does NOT occur when I run the app standalone. If I delete development.rb, the original initializers that reference my MyEngineModule::Application complain, so then I tried to delete those, and all is well.
Great, except that the original app doesn't work, since its configuration is gone.
Is there some tweak I can make to the initialization load order (or load paths, in the Engine < Rails::Engine class definition) that would prevent the original configs and initializers from being loaded when in an engine context, and allow me to leave them in place for the app context?
The simpler answer is probably this, but I'm feeling stubborn, and would like to know what it would take to make my original goal possible:
extract the code for MyEngine into an engine, remove the config/environments/* files and config/initializers/* files, and make the client app depend on this.
Make a "new" minimalist app depend on MyEngine, and move the environment files and initializers to NewApp.
Assuming I feel some unnatural compulsion to keep my original application runnable as it was, if I want to prevent the "engine" from loading the "application" configuration, what's the best way to handle that? I presume this is only really a problem during development, because I can prevent the environments/*.rb files from being pulled into the gem itself, but I like being able to test locally while I'm developing the engine and its client app.
Continuing my tradition of answering my own esoteric questions, it seems like one passable alternative is to include a guard clause in the engine's environments/*.rb and the initializers that goes something like this:
if defined? CuteEngine::Application
CuteEngine::Application.configure do
config.whatever = something
end
end
This gets around the problem of having two Rails::Application objects at a relatively small cost. Not very happy about it, but I'll live.
Bumping this for new comers.
Rails 3.1 comes with mountable engines, which sounds like exactly what you are describing. The docs aren't great for converting existing code, but it looks like this will do what you want:
module CuteEngine
class Engine < ::Rails::Engine
isolate_namespace CuteEngine
end
end
In your other app's routes.rb file, you'll add:
mount CuteEngine::Engine, at: "/cuteness"
http://edgeguides.rubyonrails.org/engines.html#mounting-the-engine
http://railscasts.com/episodes/277-mountable-engines