镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content
This repository was archived by the owner on Jun 5, 2020. It is now read-only.
This repository was archived by the owner on Jun 5, 2020. It is now read-only.

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

Open

Description

@codinkai

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.

Activity

  1. dcodeIO commented on Dec 17, 2013

    @dcodeIO
    Owner

    In Class2.js, try:

    var path = require("path"),
        Class1 = require(path.join(__dirname, "Class1.js"));
  2. codinkai commented on Dec 19, 2013

    @codinkai
    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.

  3. dcodeIO commented on Dec 19, 2013

    @dcodeIO
    Owner

    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?

  4. codinkai commented on Dec 19, 2013

    @codinkai
    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.

  5. dcodeIO commented on Dec 19, 2013

    @dcodeIO
    Owner

    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.

  6. codinkai commented on Dec 19, 2013

    @codinkai
    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"));
    
  7. dcodeIO commented on Dec 19, 2013

    @dcodeIO
    Owner

    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.

  8. codinkai commented on Dec 27, 2013

    @codinkai
    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?

  9. dcodeIO commented on Dec 27, 2013

    @dcodeIO
    Owner

    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.

  10. nerdbeere commented on Feb 23, 2016

    @nerdbeere

    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 join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions