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

[PR WELCOME] Dynamic rollup configuration // print descriptive error messages #312

Closed
DavidParks8 opened this issue Nov 23, 2017 · 15 comments · Fixed by #395
Closed

[PR WELCOME] Dynamic rollup configuration // print descriptive error messages #312

DavidParks8 opened this issue Nov 23, 2017 · 15 comments · Fixed by #395

Comments

@DavidParks8
Copy link
Member

Type of Issue

[x] Feature Request

Description

Many people seem to have the same issue with various libraries: they don't have correct rollup externals.

How To Reproduce

Look at #310, #301, #85, #119, #108, #142, #230, #163, etc...

Expected Behaviour

I suspect that a lot of these issues can be avoided by printing a more helpful error message.

Version Information

ng-packagr: v2.x.y
node: v8.x.y
@angular: v4.x.y
rxjs:
zone.js:
@alan-agius4
Copy link
Member

alan-agius4 commented Nov 26, 2017

Question, why not have externals in rollup be a function like the below so that all node modules are treated as externals ?

external: id => !(path.isAbsolute(id) || id.startsWith("."));

@DavidParks8, @dherges any feedback?

@matheo
Copy link

matheo commented Nov 28, 2017

I got a "descriptive" error message but I wonder what can I do about it.

$ node_modules/.bin/ng-packagr
Building Angular library
Generating bundle for @coachcare/common
Cleaning bundle build directory
Processing assets
Running ngc
Compiling to FESM15
'http' is imported by node_modules/axios/lib/adapters/http.js, but could not be resolved – treating it as an external dependency
'https' is imported by node_modules/axios/lib/adapters/http.js, but could not be resolved – treating it as an external dependency
preferring built-in module 'url' over local alternative at '/cli-project/node_modules/url/url.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'url' over local alternative at '/cli-project/node_modules/url/url.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
'url' is imported by node_modules/follow-redirects/index.js, but could not be resolved – treating it as an external dependency
preferring built-in module 'assert' over local alternative at '/cli-project/node_modules/assert/assert.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'assert' over local alternative at '/cli-project/node_modules/assert/assert.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
'assert' is imported by node_modules/follow-redirects/index.js, but could not be resolved – treating it as an external dependency
'http' is imported by node_modules/follow-redirects/index.js, but could not be resolved – treating it as an external dependency
'https' is imported by node_modules/follow-redirects/index.js, but could not be resolved – treating it as an external dependency
'stream' is imported by node_modules/follow-redirects/index.js, but could not be resolved – treating it as an external dependency
'tty' is imported by node_modules/follow-redirects/node_modules/debug/src/node.js, but could not be resolved – treating it as an external dependency
preferring built-in module 'util' over local alternative at '/cli-project/node_modules/util/util.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'util' over local alternative at '/cli-project/node_modules/util/util.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
'util' is imported by node_modules/follow-redirects/node_modules/debug/src/node.js, but could not be resolved – treating it as an external dependency
'os' is imported by node_modules/supports-color/index.js, but could not be resolved – treating it as an external dependency
'os' is imported by commonjs-external:os, but could not be resolved – treating it as an external dependency
'tty' is imported by commonjs-external:tty, but could not be resolved – treating it as an external dependency
preferring built-in module 'util' over local alternative at '/cli-project/node_modules/util/util.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'util' over local alternative at '/cli-project/node_modules/util/util.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'util' over local alternative at '/cli-project/node_modules/util/util.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
'util' is imported by commonjs-external:util, but could not be resolved – treating it as an external dependency
preferring built-in module 'url' over local alternative at '/cli-project/node_modules/url/url.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'url' over local alternative at '/cli-project/node_modules/url/url.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'url' over local alternative at '/cli-project/node_modules/url/url.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
'url' is imported by commonjs-external:url, but could not be resolved – treating it as an external dependency
preferring built-in module 'assert' over local alternative at '/cli-project/node_modules/assert/assert.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'assert' over local alternative at '/cli-project/node_modules/assert/assert.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'assert' over local alternative at '/cli-project/node_modules/assert/assert.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
'assert' is imported by commonjs-external:assert, but could not be resolved – treating it as an external dependency
'http' is imported by commonjs-external:http, but could not be resolved – treating it as an external dependency
'https' is imported by commonjs-external:https, but could not be resolved – treating it as an external dependency
'stream' is imported by commonjs-external:stream, but could not be resolved – treating it as an external dependency
preferring built-in module 'url' over local alternative at '/cli-project/node_modules/url/url.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
preferring built-in module 'url' over local alternative at '/cli-project/node_modules/url/url.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
'url' is imported by node_modules/axios/lib/adapters/http.js, but could not be resolved – treating it as an external dependency
'zlib' is imported by node_modules/axios/lib/adapters/http.js, but could not be resolved – treating it as an external dependency

BUILD ERROR
Unexpected token
Error: Unexpected token
    at error (/cli-project/node_modules/rollup/dist/rollup.js:185:14)
    at Module.error (/cli-project/node_modules/rollup/dist/rollup.js:16526:3)
    at tryParse (/cli-project/node_modules/rollup/dist/rollup.js:16220:10)
    at new Module (/cli-project/node_modules/rollup/dist/rollup.js:16264:15)
    at load.catch.then.then.then.source (/cli-project/node_modules/rollup/dist/rollup.js:18189:20)

error Command failed with exit code 111.

@dherges I modified locally node_modules/ng-packagr/lib/steps/rollup.js to include rollup-plugin-node-globals and node-builtins following this project that solved this kind of messages:
https://github.com/alwaysonlinetxm/rollup_issue/blob/master/rollup.config.js#L42-L43 and I realized that this was the wrong path, it's better to add as external the library using this kind of stuff, and voilá!

Thanks a lot for this awesome tool!

@oliveti
Copy link

oliveti commented Dec 5, 2017

Hi @matheo, how did you include globals() in lib.externals ?

@dherges
Copy link
Contributor

dherges commented Dec 5, 2017

@alan-agius4 Only saw your comment now. Looks good in theory .... will UMD bundles continue to work? What about the large list of rxjs mappings?

@matheo
Copy link

matheo commented Dec 5, 2017

@oliveti I found that any library requiring globals should be handled as external, so I moved to out all my dependencies requiring global stuff and voilá, ng-packagr can work take those libraries from the angular/cli project's package.json and compile the Angular related stuff only.

So, what happened to me is that I didn't declare my library my-api as external, and it requires axios and a lot of external stuff. If ng-packgr tries to include it in my Angular Components bundle, it cannot because the third party dependencies are not met. It ran fine when I declared my-lib and external, and any other requiring external libraries that are not in my project.

@dherges
Copy link
Contributor

dherges commented Dec 5, 2017

On a broader discussion: what if... we analyze the TypeScript imports (AST traversal) and set up the rollup configuration to just what your library source code needs?

2017-12-05 16_37_27-typescript ast viewer

Regarding rxjs in specific: rxjs is moving to top-level imports ... but it's still likely that users are running different versions of rxjs and use different import syntax'es.

@dherges
Copy link
Contributor

dherges commented Dec 5, 2017

@matheo @oliveti Can you please open a separate issue for your specific problem? It's good if we can keep this issue here on concept and ideas for the bundle flattening / rollup

@dherges dherges changed the title Too many similar support issues for rollup [DRAFT] Discussion: how to improve rollup integration? Dec 5, 2017
@dherges dherges added the feature label Dec 5, 2017
@alan-agius4
Copy link
Member

@dherges UMD should continue to work, the only thing that you'd need to include tslib cause of the ImportHelpers flag.

I am not quite sure how it will play with RxJs to be honest,

@dherges
Copy link
Contributor

dherges commented Dec 5, 2017

@alan-agius4 Can you verify that? Do not speculate here. For UMD, we need a mapping from the module ID (the "path" written in the import ... from '<path>' statement) to the UMD module ID (the "global-scoped object" at runtime)

Example: rxjs/symbol/observable is mapped to global.Rx.Symbol

UMD:

(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/cdk/overlay'), require('@angular/cdk/portal'), require('rxjs/observable/range'), require('rxjs/operators'), require('rxjs/Observable'), require('rxjs/operator/map'), require('rxjs/add/operator/map'), require('rxjs/add/observable/of'), require('rxjs/symbol/observable')) :
	typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/cdk/overlay', '@angular/cdk/portal', 'rxjs/observable/range', 'rxjs/operators', 'rxjs/Observable', 'rxjs/operator/map', 'rxjs/add/operator/map', 'rxjs/add/observable/of', 'rxjs/symbol/observable'], factory) :
	(factory((global.sample = global.sample || {}, global.sample.externals = {}),global.ng.core,global.ng.cdk.overlay,global.ng.cdk.portal,global.Rx.Observable,global.Rx.Observable.prototype,global.Rx,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx.Observable,global.Rx.Symbol));
}(this, (function (exports,core,overlay,portal,range,operators,Observable,map$1,map$3,of,observable) {

@alan-agius4
Copy link
Member

alan-agius4 commented Dec 6, 2017

@dherges, sorry for speculating So I did some tests and while rollup does try to provide default values for globals when you don't specify it, For RxJs and angular it' won't work one reason being is the scope.

So in order to make it work properly with Umd you's still need to provide the globals for instances that rollup cannot "guess".

So you'd still need to do something like;

external: id => !(path.isAbsolute(id) || id.startsWith("."));
globals:  (x: string) => {
      let regMatch;
      if (regMatch = /^\@angular\/(.+)/.exec(x)) {
        return `ng.${regMatch[1]}`.replace("/", ".")
      }

      if (/^rxjs\/[^/]+$/.test(x)) {
        return "Rx";
      }

      if ( /^rxjs\/(add\/)?observable\/[^/]+$/.test(x)) {
        return "Rx.Observable";
      }

      if ( /^rxjs\/(add\/)?scheduler\/[^/]+$/.test(x)) {
        return "Rx.Scheduler";
      }

      if (/^rxjs\/(add\/)?operator\/[^/]+$/.test(x)) {
        return "Rx.Observable.prototype";
      }

      return undefined; // leave it up to rollup to guess the global name

    },

Relates to: rollup/rollup-plugin-node-resolve#110

@dherges dherges changed the title [DRAFT] Discussion: how to improve rollup integration? [PR WELCOME] Dynamic rollup configuration // print descriptive error messages Dec 7, 2017
@dherges
Copy link
Contributor

dherges commented Dec 7, 2017

@alan-agius4 Looks good to me! Let's implement dynamic rollup configuration like you suggested. Before returning an undefined value, it should print a warning message.

Maybe like: Library "@your/stuff" depends on "@foo/bar". Please consider to add "@foo/bar" to the "lib.externals" section of your package file!

A pull request here is welcome!

@alan-agius4
Copy link
Member

alan-agius4 commented Dec 8, 2017

Just a small note when rollup tries to guess the name of an external, it will print out a warning telling you so, so it might be a bit redundant adding an addition warning, that said of course we can customize the message if you prefer that format.

Also, some other questions;

  • the we give the optional for user to treat an external library as non-external but rather inline it's code?
  • when specifying the externals, the users should do so as currently or they can also provide regexp?

@dherges
Copy link
Contributor

dherges commented Dec 10, 2017

Hm. Obviously, lib.externals was driven by rollup's external and global settings. So that's what it was in the past.

Now, let's switch perspective to the present. If I, as an author or maintainer of a library, write a library depending on a third-party – import { ... } from '@foo/bar'; in TypeScript code – , then I'd like to treat the third-party as a peerDependency: { "@foo/bar": "..." } and thus a rollup external – in almost every case.

There is one exception that I found and that we use in an enterprisy case: I, as a maintainer, have legacy javascript code that I'd like to embed in the bundles of my library. Why? The legacy may not be on a npm registry, it may be monkey-patched, … that sort of enterprisy things.

Why do we keep writing external when external is the 9-out-of-10 use case? Why don't we write embedded for things we'd like to embed and treat everything else as external by default?

@alan-agius4
Copy link
Member

alan-agius4 commented Dec 10, 2017 via email

@github-actions
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

This action has been performed automatically by a bot.

@github-actions github-actions bot locked and limited conversation to collaborators Jun 19, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

Successfully merging a pull request may close this issue.

5 participants