I am using RequireJS & its working fine for some modules. Recently, I added two test modules (code for the modules seems to be fine). I am importing them in my main (javascript) file and I can see that the file get imported in the browser. However, I see the following error message and I cannot troubleshoot properly what might be causing this issue. Any suggestions to fix or troubleshoot this will be greatly appreciated.
Error Message in browser
Error: No define call for urlCore/urlTest http://requirejs.org/docs/errors.html#nodefine
...{c=c[b]});return c}function C(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/er...
module to be imported:
define("urlTest", [], function() { //no dependencies on other modules
'use strict';
var urlTest = function() {
this.getTestURL = function(url, urlChk) {
if (typeof url === 'undefined' || typeof urlChk === 'undefined' ||
url === '' || urlChk === '') { //we can check length instead as well || removing typeof does not solve the issue
throw new Error("urlCommon - url or urlChk values are invalid:" + url + "|" + urlChk);
}
if (url !== null && url.length > 0 && urlChk === "Y") {
return url;
}
}; //end of getTestURL
urlTest.version = '0.0.1';
};
return urlTest;
});
I tried this but it does not work either:
/*
define("urlTest", [], function() { //no dependencies on other modules
'use strict';
return {
getTestURL : function(url, urlChk) {
if (url !== null && url.length > 0 && urlChk === "Y") {
return url;
}
}
} //end return
}); //end test module
*/
Main.js paths:
paths: {
//"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
'validateTest': 'validation/validateTest', //works
'normalizedXHR': 'xhr/normalizedXHR', //works
'urlTest': 'urlCore/urlTest', //does not work
'jsonTest': 'json/jsonTest' //does not work
}
Update:
I am using the urlTest from this module:
define('testResponse', ['./urlCore/urlTest', './json/jsonTest'], function(urlTest, jsonTest) {
'use strict';
Another Update
When I set enforceDefine to true with waitSeconds to a value greater than 0, I receive the following error (even though I see the JS file being loaded in the browser):
Error: Load timeout for modules: urlCore/urlTest
This urlTest is a dependency in a module (which sits in another directory). When I try the following, the dependencies do not load up in the browser:
define('testResponse', ['../urlCore/urlTest'], function(urlTest) {
When I try the following, the file appears to load in the browser window but I get the requirejs error stating a load timeout for module error.
define('testResponse', ['./urlCore/urlTest'], function(urlTest) {
File structure:
javascripts
javascripts/main.js
javascripts/abc/testResponse.js
javascripts/urlCore/urlTest.js
Another Update
I am able to call other modules residing in a separate directory. The issue comes forward when one of the modules in those directories e.g. abc/testResponse has a dependency on urlCore/urlTest. This appears to cause the issue for me. Should I be specifying the config part in this module as well in addition to the main.js (I'm not doing that right now).
define('testResponse', ['./urlCore/urlTest'], function(urlTest) {
When I try the ../urlCore/urlTest, the file does not event load up.
Judging by what you are showing in the question, urlTest is loaded with the path urlCore/urlTest and at this path there is a file which contains this:
define("urlTest", [], function() {
This works, so long as what RequireJS is loading a module named urlTest. No problem there. However, if you require any other module name that ultimately resolves to the path urlCore/urlTest, then you are in trouble, because the module name will not correspond to the name that you have in your define call. Or to put it differently, for your module to load when required under the name urlCore/urlTest, the define call in the module's file would have to say:
define("urlCore/urlTest", [], function() {
The easy fix for this is to not assign names to modules in your define calls. Just put the dependencies and the callback and leave the name out.
Even if you use define without specifying a module name, you still have to be careful not to end up loading the same module under two different names, because if you do, you will get a timeout when you try loading with the 2nd name. In the code you show in the question, I'd recommend using urlTest everywhere or using relative paths everywhere to load this module but don't mix the two.
Related
I followed this tutorial to create a kotlin->js project: https://kotlinlang.org/docs/tutorials/javascript/getting-started-gradle/getting-started-with-gradle.html
Next, I followed these instructions to use coroutines in my code: https://github.com/kotlin/kotlinx.coroutines/blob/master/README.md#using-in-your-projects
Everything was fine to far, no errors marked in the code and I could build my js application without any error messages. However, my js scripts are not running in the browser and I get the above mentioned error message in the browser console.
Does any of you here know what I missed or might have configured wrong?
Here's my build.gradle
group 'de.berlin'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.3.31'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin2js'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-M1"
compile("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.0-M1")
compile "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.0-M1"
}
compileKotlin2Js.kotlinOptions.sourceMap = true
compileKotlin2Js.kotlinOptions.outputFile = "${projectDir}/web/js/myApp.js"
compileKotlin2Js.kotlinOptions.suppressWarnings = false
compileKotlin2Js.kotlinOptions.verbose = true
build.doLast {
configurations.compile.each { File file ->
copy {
includeEmptyDirs = false
from zipTree(file.absolutePath)
into "${projectDir}/web/js/lib"
include { fileTreeElement ->
def path = fileTreeElement.path
path.endsWith(".js") && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))
}
}
}
copy {
includeEmptyDirs = false
from "${buildDir}/resources/main"
into "${projectDir}/web"
}
}
clean.doFirst {
delete "${projectDir}/web"
}
Everything compiles without any error message but I get the following error message in the browser console:
""Its dependency 'kotlinx-coroutines-core' was not found. Please, check whether 'kotlinx-coroutines-core' is loaded prior to '(projectname)'."
A more detailled inspection shows that /web/js/lib only contains kotlin.js, shouldn't kotlinx-coroutines-core be also there because it's part of the depencency block and schould be copied in the build.doLast-step?
I also noticed that the comiled js file contains the following:
if (typeof kotlin === 'undefined') {
throw new Error("Error loading module 'myApp'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'myApp'.");
}
if (typeof this['kotlinx-coroutines-core'] === 'undefined') {
throw new Error("Error loading module 'myApp'. Its dependency 'kotlinx-coroutines-core' was not found. Please, check whether 'kotlinx-coroutines-core' is loaded prior to 'myApp'.");
}
Why is it this['kotlinx-coroutines-core'] and not kotlinx-coroutines-core (like in the line above)?
Why is it this['kotlinx-coroutines-core'] and not kotlinx-coroutines-core (like in the line above)?
Because "kotlinx-coroutines-core" is not a valid JS identifier.
"this['kotlinx-coroutines-core']" is testing whether the module "kotlinx-coroutines-core" has been loaded or not.
if it is undefined, then it means you have not 'loaded' the module prior to the code being executed.
depending how you load JS modules, you will need to "require(....)" or have an html script reference to the "kotlinx-coroutines-core" module
It has been more than a year and a half since the thread was opened but I answer in case someone has the same problem in the future.
You have to download "kotlinx-coroutines-core" from npm. Coroutines JS - install
I'm currently experimenting with the following strategy to dynamically load a json file from a path relative to my module :
If my code is bundled as a Webpack bundle, use import(filename.json)
In any other case, fall back to an AJAX call, with an absolute path
The following seems to work fine :
function parse (fileName, callback) {
var path = "./relative/path/to/" + fileName + ".json";
var cb = process.bind(this, fileName, callback);
if (typeof webpackJsonp !== "undefined") { // <-- Test if run as Webpack bundle
// Do dynamic import
} else {
// Do Ajax call
}
}
However, I can't find any documentation on webpackJsonp, however, so I assume this is not part of Webpack's public API.
I also noticed that webpackJsonp is a function in 3.12 and an Object (inheriting from Array) in 4.28, indicating how fragile it is to rely on the presence, value or type of webpackJsonp.
Is there a (future-proof) reliable way test whether my code is being run as a Webpack bundle, using public API?
Basically, what should I replace typeof webpackJsonp !== "undefined" with, to achieve the same effect, but using public API?
Additionally, I'm also having some problems with getting the actual import to work in Webpack 4.28. See import() breaks in Angular 7.2.3 + Webpack 4.28 for that.
I tried to load Cycle DOM from their CDN through SystemJS with something like:
System.config({
map: {
'cycle-dom': 'https://unpkg.com/#cycle/dom#17.1.0/dist/cycle-dom.js',
'xstream': 'https://cdnjs.cloudflare.com/ajax/libs/xstream/10.3.0/xstream.min.js',
}
});
System.import('cycle-dom', cycleDOM => {
...
});
But I quickly found out cycle-dom needs xstream. So I try to load both:
Promise.all([
System.import('xstream'),
System.import('cycle-dom')
])
.then(([xs, cycleDOM]) => {
...
});
But I still get the same error. It looks like cycle-dom is expecting xstream to exist on window when it's first loaded. So I tried:
System.import('xstream')
.then(xs => window['xstream'] = xs)
.then(() => System.import('cycle-dom'))
.then(cycleDOM => {
...
});
I feel like I'm going about this all wrong. How can I do this?
Update:
Following martin's advice below, I tried configuring xstream as a dependency of cycle-dom.
Here's a jsbin that demonstrates. What I'm doing is loading cycle-run and cycle-dom and then running the example off the cycle home page.
But I get the error:
"TypeError: Cannot read property 'default' of undefined"
Undefined in this case is cycle-dom trying to load window['xstream'], which isn't being loaded.
Thanks.
The System.import() call returns a Promise so you need to put the callback into its then() method (the second parameter is the parent name; not a callback).
System.import('cycle-dom').then(function(cycleDOM) {
console.log(cycleDOM);
});
This prints the module exports.
I don't have any experience with cycle.js so I can't tell whether this is enough or not. Nonetheless you can set this package dependencies with meta config:
System.config({
map: {
'cycle-dom': 'https://unpkg.com/#cycle/dom#17.1.0/dist/cycle-dom.js',
'xstream': 'https://cdnjs.cloudflare.com/ajax/libs/xstream/10.3.0/xstream.min.js',
},
meta: {
'cycle-dom': {
deps: [
'xstream'
]
}
}
});
Again, I don't know whether this is enough or not. The SystemJS documentation contains pretty well explained example how to load dependencies that need to register some global variables. See https://github.com/systemjs/systemjs/blob/master/docs/module-formats.md#shim-dependencies
Edit:
In this case it's a little more complicated. The cycle-run.js script is generated probably by browserify and you can see it contains a line as follows:
var xstream_1 = (typeof window !== "undefined" ? window['xstream'] : typeof global !== "undefined" ? global['xstream'] : null);
This checks whether window['xstream'] exists when it's loaded. This means that the xstream has to be loaded before loading the cycle-run.js script. The way SystemJS works is that it loads the requested module and then loads its dependencies (you can see the order in Developer Tools). So it's the opposite order than you need (this is very similar to my question on SystemJS GitHub page).
This means you need to restructure the import calls:
System.config({
// ...
meta: {
'xstream': {
format: 'global',
exports: 'xstream',
}
}
});
System.import('xstream').then(function() {
Promise.all([
System.import('cycle-run'),
System.import('cycle-dom'),
])
.then(([cycle, cycleDOM]) => {
// ...
});
});
This registers the xstream before loading cycle-run. Also with the meta configuration for xstream this ensures that the window.xstream exists only inside these callbacks and doesn't leak to the global scope.
See your updated demo: https://jsbin.com/qadezus/35/edit?js,output
Also to use format and exports you need to use the newer SystemJS 0.20.* and not 0.19.*.
While working on a Web app using Webpack to manage JavaScript dependencies, I stumbled upon the problem i'm going to describe.
Loading dependencies passing strings to require() works beautifully:
// main.js
var jQuery = require('jquery');
Here, jquery is installed with Bower, and Webpack is correctly configured to automatically resolve Bower modules.
Now, I'm working on the problem of conditionally loading modules, with particular regard to the situation where modules have to be downloaded from a CDN, or from the local server if the CDN fails. I use scriptjs to asynchronously load from the CDN, by the way. The code I'm writing is something like this:
var jQuery = undefined;
try {
jQuery = require('jquery-cdn');
} catch (e) {
console.log('Unable to load jQuery from CDN. Loading local version...');
require('script!jquery');
jQuery = window.jQuery;
}
// jQuery available here
and this code works beautifully as well.
Now, since I obviously have a lot of dependencies (Handlebars, Ember, etc.) that I want to try to load from a CDN first, this code starts to get a little redundant, so the most logical thing I try to do is to refactor it out into a function:
function loadModule(module, object) {
var lib = undefined;
try {
lib = require(module + '-cdn');
} catch (e) {
console.log('Cannot load ' + object + ' from CDN. Loading local version...');
require('script!' + module);
lib = window[object];
}
return lib;
}
var jQuery = loadModule('jquery', 'jQuery');
var Handlebars = loadModule('handlebars', 'Handlebars');
// etc...
The problem is that Webpack has a particular behaviour when dealing with expressions inside require statements, that hinders my attempts to load modules in the way described above. In particular, when using an expression inside require it
tries to include all files that are possible with your expression
The net effect is a huge pile of error messages when I try to run Webpack with the above code.
Though the linked resources suggest to explicitly declare the path of the JavaScript files to include, what I fail to get is how to do the same thing when I cannot, or don't want to, pass a precise path to require, but rather use the automatically resolved modules, as shown.
Thanks all
EDIT:
I still don't known how to use expressions to load those scripts, however, I designed a workaround. Basically, the idea is to explicitly write the require('script') inside a callback function, and then dinamically call that function when it's time. More precisely, I prepared a configuration file like this:
// config.js
'use strict';
module.exports = {
'lib': {
'jquery': {
'object': 'jQuery',
'dev': function() { require('script!jquery'); },
'dist': function() { return require('jquery-cdn'); },
'cdn': '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'
},
'handlebars': {
// ...
}
}
};
Inside my main code I, then, define an array of resources to load, like:
var config = require('./config.js');
var resources = [ config.lib.jquery, config.lib.handlebars, ... ];
And then when I have to load the development version, or the distribution version, I dinamically call:
// Inside some kind of cycle
// resource = resources[index]
try {
window[resource.object] = resource.dist();
} catch (e) {
console.log('Cannot load ' + resource.object + ' from CDN. Loading local version...');
resource.dev();
}
Here there's a more complete example of this in action.
According to apple's documentation I can import one JS file into another with an import statement. And yes I am able to use JS functions and recursively call other JS functions.
But can I include node modules into my automation. Node/npm module seems to have a lot of tools that makes life easier and avoid code duplication.
And actually I was able to use one node module called moment.js through the following call in my code
#import "../node_modules/moment/moment.js"
But I am not have the same luck with other npm modules. I tried couple Faker.js, Charlatan.js and I getting the following error in Faker.js
Script threw an uncaught JavaScript error: Can't find variable: window
on line 618 of Faker.js
Looking at *.js files it looks like it has something to do with the way these modules are packaged. My JS knowledge isn't getting me anywhere.
The last few lines of moment js file
// CommonJS module is defined
if (hasModule) {
module.exports = moment;
}
/*global ender:false */
if (typeof ender === 'undefined') {
// here, `this` means `window` in the browser, or `global` on the server
// add `moment` as a global object via a string identifier,
// for Closure Compiler "advanced" mode
this['moment'] = moment;
}
/*global define:false */
if (typeof define === "function" && define.amd) {
define("moment", [], function () {
return moment;
});
}
Last few lines of Faker js file
if (typeof define == 'function'){
define(function(){
return Faker;
});
}
else if(typeof module !== 'undefined' && module.exports) {
module.exports = Faker;
}
else {
window.Faker = Faker;
}
I am perfectly able to play with these modules in node console, so nothing wrong with the modules, it just how to include/require them in my JS files.
Had to do two things for Faker to work for me
remove 'use strict'
Check if window is undefined
Add this statement
this['Faker'] = Faker;