Skip to content
This repository has been archived by the owner on Jun 5, 2020. It is now read-only.

Error: Cannot find module './*.js' #10

Open
codinkai opened this issue Dec 17, 2013 · 11 comments
Open

Error: Cannot find module './*.js' #10

codinkai opened this issue Dec 17, 2013 · 11 comments
Labels

Comments

@codinkai
Copy link

Hi,

my project has the following structure:

index.js
compile.js
lib/
-- Class1.js
-- Class2.js
package.json

In compile.js the compiler is invoked with index.js and all files in the lib-directory as source files. Compilation works as expected.

But when I invoked the compiled source file, cross-references between Class1.js and Class2.js cannot be found. The following error occurs:

module.js:340
throw err;
^
Error: Cannot find module './Class1.js'

In Class2.js there is a reference to Class1.js with require(''./Class1.js').

I could use absolute paths by setting an environment-variable in index.js and reading this in every require-statement. But I would like to know which is the best-practice solution for this problem.

@dcodeIO
Copy link
Owner

dcodeIO commented Dec 17, 2013

In Class2.js, try:

var path = require("path"),
    Class1 = require(path.join(__dirname, "Class1.js"));

@codinkai
Copy link
Author

Unfortunately this does not work. I would expect the require statement to get removed, because the required-file is in the compiler's source directory. If I would use absolute paths uncompiled sources would be loaded, which compiled version might be in the compilation result.

@dcodeIO
Copy link
Owner

dcodeIO commented Dec 19, 2013

I am sorry, I do not seem to understand this fully. Of course you can change the require statement to whatever you like, for example: require(path.join(__dirname, "..", "Class1.js")); with __dirname being just a reference to the current directory of the file. If you are using ADVANCED_OPTIMIZATIONS, it might also be required to add externs so that the __dirname variable does not become renamed by CC. Or what am I getting wrong?

@codinkai
Copy link
Author

The closure compiler concatenates the three source files lib/Class1.js, lib/Class2.js and index.js and compiles them into a file, called compiled.js. The compiled.js should not reference to any of the uncompiled files with a require statement.

@dcodeIO
Copy link
Owner

dcodeIO commented Dec 19, 2013

I see. In that case, you might want to give Preprocessor a try to bundle your files, possibly leaving stuff out, prior to compilation.

There are also some CC switches for commonjs but I haven't used these, yet.

Just to make this clear: I cannot change the way Closure Compiler works, as ClosureCompiler.js is just a wrapper around it.

@codinkai
Copy link
Author

You are right, but some preprocessing could be added like replacing require-statements to source-files with assignments.

I only want the compiler to make static type check to my sources. I do not care about the result right now. How would you handle the following situtation?

// index.js
var TestClass = require('lib/TestClass.js');

// compiler should throw an error (does concatenation)
console.log(TestClass.add("hello", "world"));
// lib/TestClass.js
var TestClass = function() {};

/**
 * @type {number}
 */ 
TestClass.prototype.attribute = "some initial value";

/**
 * Adds two numbers.
 * 
 * @param {number} a Operand a.
 * @param {number} b Operand b.
 * @return {number} Sum of a and b.
 */
TestClass.prototype.add = function(a, b) {
  return a+b;
}

module.exports = TestClass;

The compilation for these files should fail due to the wrong invocation of "add" with strings instead of numbers AND the wrong type of the attribute. But I do get the following compilation result:

function a() {
}
a.prototype.add = function(b, c) {
  return b + c;
};
module.a = a;
a = require("lib/TestClass.js");
console.log(a.add("hello", "world"));

@codinkai codinkai reopened this Dec 19, 2013
@dcodeIO
Copy link
Owner

dcodeIO commented Dec 19, 2013

What I found on this: http://www.nonblocking.io/2011/12/experimental-support-for-common-js-and.html (CC internal)

Maybe this could be useful, too: http://browserify.org/ (bundles require statements)

Or, like mentioned above, using Preprocessor.js prior to compilation, e.g. by adding conditional blocks

var Class1;

// #ifdef SINGLEFILE
Class1 = (function() {
    var module = {"exports": {}};
    // #include "Class1.js"
    return module.exports;
})();
// #else
Class1 = require("Class1.js");
// #endif

^ This will require the file if run without Preprocessor as the inline function will return {} and not include anything. When run with Preprocessor with SINGLEFILE=true, it will include the file instead, making it safe to be compiled through CC afterwards. ProtoBuf.js uses Preprocessor.js for example for building different versions of the library prior to CC compilation.

@codinkai
Copy link
Author

TypeChecking works, when I invoke the compiler as follows. But I have the same problems as in https://groups.google.com/forum/#!topic/closure-compiler-discuss/1hPmS7EOhj8. Unfortunately I haven't found a solution for it yet.

./node_modules/closurecompiler/bin/ccjs index.js lib/TestClass.js --process_common_js_modules --common_js_entry_module=index.js --compilation_level=ADVANCED_OPTIMIZATIONS --formatting=pretty_print --warning_level=VERBOSE

By the way, how do I pass flag-options to the ClosureCompiler class?

@codinkai
Copy link
Author

@dcodeIO
Copy link
Owner

dcodeIO commented Dec 27, 2013

So, I guess CC's CommonJS support is far from being usable.

To pass options (any that closure compiler supports) to ClosureCompiler.js:

  • new ClosureCompiler(options)
  • ClosureCompiler.compile(files, options, callback)
  • Or on the command line to ccjs

Remains browserify and Preprocessor.js. I am sorry that I cannot assist you any further, it's just that I am not a maintainer of closure compiler itself, only of this package.

@nerdbeere
Copy link

Closure Compiler itself works fine for me with the following command: closure-compiler --process_common_js_modules --common_js_entry_module=./src/index.js --externs=./externs.js --compilation_level=ADVANCED_OPTIMIZATIONS src

However when I try to use ccjs I get the error Illegal source file after options: src.

Then I tried using ccjs like this: ccjs ./src/index.js --process_common_js_modules --common_js_entry_module=./src/index.js --externs=./externs.js --compilation_level=ADVANCED_OPTIMIZATIONS
Now it tells me that it can't resolve the module.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants