Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPM Module with main index.ts source file is recognised as a bundle item and thus not being bundled #319

Closed
silkentrance opened this issue Feb 5, 2019 · 13 comments
Labels

Comments

@silkentrance
Copy link
Contributor

silkentrance commented Feb 5, 2019

I am using karma-typescript@4.0.0 together with karma-typescript-es6-transform@4.0.0.

Currently I am working on mocha-typescript and an integration test for it using karma and of course karma-typescript.

Everything worked fine so far, however, we also have a mocha-typescript-di-typedi package that will have no exports and is imported so that it can register its handler with mocha-typescript.

Here is the example code

// example taken from karma-typescript
import { suite, test } from "mocha-typescript";
import "mocha-typescript-di-typedi";
import { HelloService } from "./hello-service.interface";
import { HelloComponent } from "./hello.component";

class MockHelloService implements HelloService {

    public sayHello(): string {
        return "Hello karma!";
    }
}

@suite
class HelloKarmaTest {
  @test
  shouldSayHelloKarma() {

    let mockHelloService = new MockHelloService();
    let helloComponent = new HelloComponent(mockHelloService);

    expect(helloComponent.sayHello()).to.be("Hello karma!");
  }
}

The offending line is import "mocha-typescript-di-typedi";. It seems that the parser will overlook this as a valid import and thus will not bundle it. As a consequence, the test will fail when it comes to requiring this module, resulting in

HeadlessChrome 71.0.3578 (Mac OS X 10.13.6) ERROR
  {
    "message": "Uncaught Error: Can't find mocha-typescript-di-typedi [/Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/node_modules/mocha-typescript-di-typedi/index.ts] (required by /Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/src/hello.component.spec.ts)\nat /Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/node_modules/karma-typescript/dist/client/commonjs.js:13:

I finally got it to work by changing the import statement to import * as UNUSED from "mocha-typescript-di-typedi";.

With this in place, everything will be bundled and the test will work just fine. (not having tested the dependency injection yet but I am confident.)

However, I'd rather not use this kludge and I am sure that our users will not understand why it would have to be this way 😁.

Either way. Thank you very much for this fine piece of software!

BTW if you want to have a look at the integration test, it is in the https://github.com/pana-cc/mocha-typescript/tree/gh-157 branch. Please note that setting up the integration-test/karma* packages is a manual process as we need to package everything using module: "es6" and target: "es6". The default in the packages is currently module: "commonjs" and target: "es6".

@silkentrance
Copy link
Contributor Author

silkentrance commented Feb 6, 2019

Here is a failing build with the import "mocha-typescript-di-typedi"; in place:

https://travis-ci.org/pana-cc/mocha-typescript/jobs/489308975

and here is a succeeding build with the "kludge" in place:

https://travis-ci.org/pana-cc/mocha-typescript/jobs/489311328

@erikbarke
Copy link
Collaborator

If you look at the transpiled code, what does Typescript transpile import "mocha-typescript-di-typedi"; as? Does it become a require like import * as UNUSED from "mocha-typescript-di-typedi";

@silkentrance
Copy link
Contributor Author

silkentrance commented Feb 6, 2019

According to TS AstViewer, the AST representation, on which you are working, is an ImportDeclaration with just a StringLiteral.

And the transpiled source reads require("mocha-typescript-di-typedi");.

And when debugging through the resolver and bundler, also the compiler, it shows that in the resolver, the package is recognised as a dependency of the spec.ts module but it is never bundled.

@silkentrance
Copy link
Contributor Author

I have added some extra log.debug statements and this is what I get from the various components in the system

6 02 2019 20:52:42.592:DEBUG [dependency-walker.karma-typescript]: bundling mocha-typescript
06 02 2019 20:52:42.593:DEBUG [dependency-walker.karma-typescript]: add dependency mocha-typescript -> /Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/node_modules/mocha-typescript/index.d.ts
06 02 2019 20:52:42.593:DEBUG [dependency-walker.karma-typescript]: bundling mocha-typescript-di-typedi
06 02 2019 20:52:42.593:DEBUG [dependency-walker.karma-typescript]: add dependency mocha-typescript-di-typedi -> /Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/node_modules/mocha-typescript-di-typedi/index.ts
06 02 2019 20:52:42.593:DEBUG [dependency-walker.karma-typescript]: bundling ./hello-service.interface
06 02 2019 20:52:42.593:DEBUG [dependency-walker.karma-typescript]: add dependency ./hello-service.interface -> /Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/src/hello-service.interface.ts
06 02 2019 20:52:42.593:DEBUG [dependency-walker.karma-typescript]: bundling ./hello.component
06 02 2019 20:52:42.594:DEBUG [dependency-walker.karma-typescript]: add dependency ./hello.component -> /Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/src/hello.component.ts
06 02 2019 20:52:42.594:DEBUG [dependency-walker.karma-typescript]: bundling ./hello-service.interface
06 02 2019 20:52:42.594:DEBUG [dependency-walker.karma-typescript]: add dependency ./hello-service.interface -> /Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/src/hello-service.interface.ts
06 02 2019 20:52:42.595:DEBUG [bundler.karma-typescript]: Project has 5 import/require statements, code will be bundled
06 02 2019 20:52:42.597:DEBUG [resolver.karma-typescript]: resolved bundleItem
06 02 2019 20:52:42.598:DEBUG [resolver.karma-typescript]: BundleItem {
  moduleName: 'mocha-typescript-di-typedi',
  filename: '/Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/node_modules/mocha-typescript-di-typedi/index.ts',
  source: undefined,
  sourceMap: undefined,
  dependencies: [],
  transformedScript: false }
06 02 2019 20:52:42.598:DEBUG [resolver.karma-typescript]: resolved bundleItem
06 02 2019 20:52:42.598:DEBUG [resolver.karma-typescript]: BundleItem {
  moduleName: './hello-service.interface',
  filename: '/Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/src/hello-service.interface.ts',
  source: undefined,
  sourceMap: undefined,
  dependencies: [],
  transformedScript: false }
06 02 2019 20:52:42.599:DEBUG [resolver.karma-typescript]: resolved bundleItem
06 02 2019 20:52:42.599:DEBUG [resolver.karma-typescript]: BundleItem {
  moduleName: './hello.component',
  filename: '/Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/src/hello.component.ts',
  source: undefined,
  sourceMap: undefined,
  dependencies: [],
  transformedScript: false }
06 02 2019 20:52:42.599:DEBUG [resolver.karma-typescript]: resolved bundleItem
06 02 2019 20:52:42.599:DEBUG [resolver.karma-typescript]: BundleItem {
  moduleName: './hello-service.interface',
  filename: '/Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/src/hello-service.interface.ts',
  source: undefined,
  sourceMap: undefined,
  dependencies: [],
  transformedScript: false }

As you can see, the package is actually added as a bundle item.

@silkentrance
Copy link
Contributor Author

silkentrance commented Feb 6, 2019

I think it should not have been added as a bundle item, mocha-typescript at least isn't, which is also an import of hello.component.spec.ts, but then again, mocha-typescript is initially recognised as a .d.ts file which is later being corrected into a .ts file.

@silkentrance
Copy link
Contributor Author

silkentrance commented Feb 6, 2019

After having removed the typings entry from mocha-typescript package.json, mocha-typescript was also recognised as .ts.

This basically boils down to the fact that typescript files, while they are not being part of the current project are recognised as typescript files and will thus become bundle items. In turn, these external resources will never be processed:

    "message": "Uncaught Error: Can't find mocha-typescript [/Volumes/workspaces/01-coldrye/01-collaboration/mocha-typescript/integration-test/karma-di-typedi/node_modules/mocha-typescript/index.ts] (required by /Volumes/workspaces/01-c

It seems that we need to rethink our packaging strategy.

On your end, it seems that you at least should make sure that it is both a typescript file and also belonging to the current project, i.e. is not an external module.

@silkentrance
Copy link
Contributor Author

The fix is rather simple. I will provide a PR for this.

@silkentrance
Copy link
Contributor Author

silkentrance commented Feb 6, 2019

But, given your current build/test process, it will be a hell of an undertaking to provide tests for this.

This will need an external package.

Did you know that you can also make integration test/example packages part of the lerna.json#packages, too? See https://github.com/pana-cc/mocha-typescript/tree/gh-157 which does just that. While definitely not perfect and not working up to our expectations just yet, it will definitely leverage the need for additional setup and test scripts in the root package.json.

Also, referenced local dependencies must be fixed to the current version, e.g. ^1.2.0, in order for lerna to not fetch the dependency from a npm registry but resolve it by linking to the local package. It might also be npm that just does that, I don't know...

The required external package that exposes the handled behaviour (include typescript sources) would then be local to the project, too.

silkentrance added a commit to coldrye-collaboration/karma-typescript that referenced this issue Feb 6, 2019
@silkentrance silkentrance changed the title Module with no exports is not bundled NPM Module with main index.ts source file is recognised as a bundle item and thus not being bundled Feb 6, 2019
@erikbarke
Copy link
Collaborator

I tried to make the tests and example packages a part of the lerna monorepo packages but had to give up because of Karma looking for plugins only in the local node_modules folder, how on earth did you get around that?

erikbarke added a commit that referenced this issue Feb 7, 2019
Fix #319: external npm modules must not become bundle items
@silkentrance
Copy link
Contributor Author

silkentrance commented Feb 7, 2019

Um, well, I did not do anything 😄

{
  "name": "karma-plain",
  "private": true,
  "version": "1.0.0",
  "description": "Integration test showing karma and mocha-typescript are working like a charm",
  "devDependencies": {
    "@types/expect.js": "latest",
    "@types/mocha": "^5.2.5",
    "expect.js": "latest",
    "karma": "latest",
    "karma-chrome-launcher": "latest",
    "karma-mocha": "latest",
    "karma-mocha-reporter": "latest",
    "karma-typescript": "latest",
    "mocha": "^5.2.0",
    "mocha-typescript": "^1.2.0",
    "typescript": "^3.2.1"
  },
  "scripts": {
    "test": "karma start"
  }
}

The karma frameworks will be hoisted to top level. However, I think that I do not have any plugins...
let me try that.

Ok, adding the plugins section to the karma.conf.ts did give me some problems but I found out that you need to list all plugins when using it

So, with this in place, karma also find the packages that had been hoisted by lerna

    plugins: [
      'karma-mocha',
      'karma-chrome-launcher',
      'karma-typescript',
      'karma-typescript-es6-transform'
    ]

@erikbarke
Copy link
Collaborator

Haha, ok, I gonna give the tests and lerna another try 🚀

@erikbarke
Copy link
Collaborator

And that's a no 😞I'm just gonna leave this here for future me:

  • karma gets hoisted to ./node_modules/karma
  • karma-typescript gets symlinked to ./examples/typescript-latest/node_modules
  • ./node_modules/karma/lib/plugin.js executes with __dirname /node_modules/karma/lib
  • requiring karma_typescript fails because Node.js couldn't possibly know that it should look inside ./examples/typescript-latest/node_modules when executing in ./node_modules/karma/lib

It was worth a shot, but I guess I'm stuck with the package.json scripts.

@silkentrance
Copy link
Contributor Author

I will try figure this one out, as it works perfectly fine on the gh-157 branch for mocha-typescript.

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

No branches or pull requests

2 participants