I've started using the intern library to write functional tests in js, and I realized that I couldn't understand this syntax:
var assert = require('intern/chai!assert');
var registerSuite = require('intern!object');
What is the purpose of the ! character in the argument of the require() method?
Short answer
It identifies a resource that is part of a plugin.
The structure of the identifier is: [plugin]![resource].
Long answer
In the documentation, you can find that:
Intern is built on top of a standard amd loader, which means that its modules are also normally written in the AMD module format.
That's why and how the require function is actually injected, so it's clear that you are not using the require module provided along with Node.JS.
It states also that:
[AMD format] Allows modules and other assets to be asynchronously or conditionally resolved by writing simple loader plugins
If you follow the link provided with the documentation when it cites the loaders, you find that:
Loader plugins extend an AMD implementation by allowing loading of resources that are not traditional JavaScript dependencies.
In particular, you can find that a dependency has the following form:
[Plugin Module ID]![resource ID]
It goes without saying that the default implementation of the loader you get by using intern adheres to the above mentioned standard.
That said, it follows that, if we consider:
intern/chai!assert
You can read it as inter/chai as plugin module and assert as actually required resource.
The purpose of the ! character in the argument of the require() method is to satisfy the requirements of the syntax used to identify a resource that is itself part of a plugin.
I got this answer for you extracted from this similiar question and very well explained by explunit:
The exclamation point syntax is reserved for plugins. Typically there would be something else following the exclamation point which indicates the resource that the plugin would load, e.g. text!myTemplate.html, but in the case of domReady! the plugin exists just as a way to wait until DOM loaded before invoking your callback function, so nothing needs to follow the exclamation point.
Related
In webpack 1 docs is statement that in webpack 2 will use System.import() for dynamic require:
Luckily, there is a JavaScript API “loader” specification being
written to handle the dynamic use case: System.load (or
System.import). This API will be the native equivalent to the above
require variations.
And during that time all around the web was examples of using this System.import().
Before releasing webpack 2, authors decide to change System.import() to import():
add import() as Code Splitting construct. It should be used instead of
System.import when possible. System.import will be deprecated in
webpack 2 release (removed in webpack 3) as it's behavior is incorrect
according to the spec.
This import() is based on tc39/proposal-dynamic-import specification, and you can read more why they made this change here.
Can someone explain difference between System.import() and import()?
Despite different name, usage looks the same:
import(modulePath)
.then(module => module.default())
.catch(/* ... */);
System.import(modulePath)
.then(module => module.default())
.catch(/* ... */);
But in weback 2 doc is: "System.import() behavior is incorrect according to the spec" - so it suggest that there is difference between System.import() and import().
Here's what you're looking for: tc39 Proposal for Import
An actual function
Drafts of the Loader ideas collection have at various times had actual functions (not just function-like syntactic forms) named System.import() or System.loader.import() or similar, which accomplish the same use cases.
The biggest problem here, as previously noted by the spec's editors, is how to interpret the specifier argument to these functions. Since these are just functions, which are the same across the entire Realm and do not vary per script or module, the function must interpret its argument the same no matter from where it is called. (Unless something truly weird like stack inspection is implemented.) So likely this runs into similar problems as the document base URL issue for the importModule function above, where relative module specifiers become a bug farm and mismatch any nearby import declarations.
When declaring qx.log.appender.Native or qx.log.appender.Console, my IDE (PyCharm) complains about the syntax:
// Enable logging in debug variant
if (qx.core.Environment.get("qx.debug"))
{
qx.log.appender.Native;
qx.log.appender.Console;
}
(as documented here)
The warning I get is
Expression statement is not assignment or call
Is this preprocessor magic or a feature of JavaScript syntax I'm not aware yet?
Clarification as my question is ambiguous:
I know that this is perfectly fine JavaScript syntax. From the comments I conclude that here's no magic JS behavior that causes the log appenders to be attached, but rather some preprocessor feature?!
But how does this work? Is it an hardcoded handling or is this syntax available for all classes which follow a specific convention?
The hints how to turn off linter warnings are useful, but I rather wanted to know how this "magic" works
Although what's there by default is legal code, I find it to be somewhat ugly since it's a "useless statement" (result is ignored), aside from the fact that my editor complains about it too. In my code I always change it to something like this:
var appender;
appender = qx.log.appender.Native;
appender = qx.log.appender.Console;
Derrell
The generator reads your code to determine what classes are required by your application, so that it can produce an optimised application with only the minimum classes.
Those two lines are valid Javascript syntax, and exist in order to create a reference to the two classes so that the generator knows to include them - without them, you wouldn't have any logging in your application.
Another way to create the references is to use the #use compiler hint in a class comment, eg:
/**
* #use(qx.log.appender.Native)
* #use(qx.log.appender.Console)
*/
qx.Class.define("mypackage.Application", {
extend: qx.application.Standalone,
members: {
main: function() {
this.base(arguments);
this.debug("Hello world");
}
}
});
This works just as well and there is no unusual syntax - however, in this version your app will always refer to the those log appenders, whereas in the skeleton you are using the references to qx.log.appender.Native/Console were surrounded by if (qx.core.Environment.get("qx.debug")) {...} which means that in the non-debug, ./generate.py build version of your app the log appenders would normally be excluded.
Whether you think this is a good thing or not is up to you - personally, these days I ship all applications with the log appenders enabled and working so that if someone has a problem I can look at the logs (you can write your own appender that sends the logs to the server, or just remote control the user's computer)
EDIT: One other detail is that when a class is created, it can have a defer function that does extra initialisation - in this case, the generator detects qx.log.appender.Console is needed so it makes sure the class is loaded; the class' defer method then adds itself as an appender to the Qooxdoo logging system
This is a valid JS syntax, so most likely it's linter's/preprocessor's warning (looks like something similar to ESLint's no-unused-expressions).
Edit:
For the other part of the question - this syntax most likely uses getters or (rather unlikely as it is a new feature) Proxies. MDN provides simple examples of how this works under the hood.
Btw: there is no such thing as "native" JS preprocessor. There are compilers like Babel or TypeScript's compiler, but they are separate projects, not related to the vanilla JavaScript.
Uncompressed jQuery file: http://code.jquery.com/jquery-2.0.3.js
jQuery Source code: https://github.com/jquery/jquery/blob/master/src/core.js
What are they doing to make it seem like the final output is not using Require.js under the hood? Require.js examples tells you to insert the entire library into your code to make it work standalone as a single file.
Almond.js, a smaller version of Require.js also tell you to insert itself into your code to have a standalone javascript file.
When minified, I don't care for extra bloat, it's only a few extra killobytes (for almond.js), but unminified is barely readable. I have to scroll all the way down, past almond.js code to see my application logic.
Question
How can I make my code to be similar to jQuery, in which the final output does not look like a Frankenweenie?
Short answer:
You have to create your own custom build procedure.
Long answer
jQuery's build procedure works only because jQuery defines its modules according to a pattern that allows a convert function to transform the source into a distributed file that does not use define. If anyone wants to replicate what jQuery does, there's no shortcut: 1) the modules have to be designed according to a pattern which will allow stripping out the define calls, and 2) you have to have a custom conversion function. That's what jQuery does. The entire logic that combines the jQuery modules into one file is in build/tasks/build.js.
This file defines a custom configuration that it passes to r.js. The important option are:
out which is set to "dist/jquery.js". This is the single
file produced by the optimization.
wrap.startFile which is set to "src/intro.js". This file
will be prepended to dist/jquery.js.
wrap.endFile which is set to "src/outro.js". This file will
be appended to dist/jquery.js.
onBuildWrite which is set to convert. This is a custom function.
The convert function is called every time r.js wants to output a module into the final output file. The output of that function is what r.js writes to the final file. It does the following:
If a module is from the var/ directory, the module will be
transformed as follows. Let's take the case of
src/var/toString.js:
define([
"./class2type"
], function( class2type ) {
return class2type.toString;
});
It will become:
var toString = class2type.toString;
Otherwise, the define(...) call is replace with the contents of the callback passed to define, the final return statement is stripped and any assignments to exports are stripped.
I've omitted details that do not specifically pertain to your question.
You can use a tool called AMDClean by gfranko https://www.npmjs.org/package/amdclean
It's much simpler than what jQuery is doing and you can set it up quickly.
All you need to do is to create a very abstract module (the one that you want to expose to global scope) and include all your sub modules in it.
Another alternative that I've recently been using is browserify. You can export/import your modules the NodeJS way and use them in any browser. You need to compile them before using it. It also has gulp and grunt plugins for setting up a workflow. For better explanations read the documentations on browserify.org.
Is there a way to dynamically resolve paths with RequireJS? For example, is it possible to configure it so that, if I do
require(['mymodule'], function(mod){ });
some sort of function of mine will be called, with "mymodule" being passed as a parameter, and with the value I return therefrom being used by Require as the path to use for mymodule?
I do understand that Require has some wonderful convention over configuration with respect to path resolution, and I also understand that paths can be manually configured. But right now I'm trying to add in RequireJS to an old project that was written without Require in mind, so I'm trying to see what all of my options are.
You might be best served by implementing a loader plugin.
Not sure if it's a problem for you, but this would mean your require syntax would turn into something like this:
require(['myplugin!mymodule'], function(mod){ });
The specific method you would use is normalize:
normalize is called to normalize the name used to identify a resource. Some resources could use relative paths, and need to be normalized to the full path. normalize is called with the following arguments:
EDIT: I see there's a replace plugin listed on the plugins wiki which sounds similar to what you are trying to do. It uses only the load method, so apparently what I said above about the normalize method is not a blanket rule.
If the path is truly dynamic, this won't help, but if you just need to modify how the legacy script is returned back to your modules (e.g. taking two different globals and putting them under a different top-level global), you might also think about using the init hook in the shim config option
EDIT 2: some related hacks are posted in this question: Configuring RequireJS to load from multiple CDNs
I have come across JSHint but was hoping it would validate node.js syntax but it doesn't, for example if I do:
var server = http.createServerfunctionThatDoesNotExists(function(request, response) {....
The test passes even though there isn't a function called createServerfunctionThatDoesNotExists
What am I missing with JSHint and the node.js option?
I think it doesn't dig into CommonJS modules as they can contain virtually everything.
So even if you are require'ing http it could be your own module with any interface.
'Assume Node' means it tolerates global variables like module or exports
JSHint is basically JSLint and is more for syntax/style/JS-nonos rather than a deep-scan product that executes your JS. Fully vetting JS code (or any dynamic language, really, depending on your definition of dynamic) pretty much requires running it, since things like methods can be defined more or less anywhere, including at runtime.
JSHint does go a bit further and allow the definition of high-level constructs used by some JS libraries.