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

Proposal: Provide a way to add externals to webpack config #2141

Closed
MrChoclate opened this issue Sep 15, 2016 · 12 comments · Fixed by #3814
Closed

Proposal: Provide a way to add externals to webpack config #2141

MrChoclate opened this issue Sep 15, 2016 · 12 comments · Fixed by #3814
Assignees
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful type: bug/fix

Comments

@MrChoclate
Copy link

The issue is that if I use global script via app[0].scripts I cannot use it again in my .ts files.

Example: if I have:

      "scripts": [
        "../node_modules/jquery/dist/jquery.js",
        "../node_modules/moment/moment.js",
        "../node_modules/fullcalendar/dist/fullcalendar.min.js"
      ],

I cannot do: import * as moment from 'moment';. If I do so, moment will become an empty object. Of course, I can use it without importing it since it is global BUT other libs that depends on moment (angular2-moment in my case) will do import * as moment from 'moment';, they will get an empty object and their code will break.
Then I cannot use this libs. (I think #1974 is related)

I cannot remove moment from scripts since I have other global scripts that depend on it (fullcalendar). Maybe there is a way to make all this scripts work without apps[0].scripts but I have not found it.

My solution is to use webpack externals https://webpack.github.io/docs/library-and-externals.html

If I add

externals: {
      'moment': 'moment'
    },

to webpack-build-common.ts it is working.

I can provide a PR adding externals from apps[0].externals to the webpack config. Is it the right solution?

@clydin
Copy link
Member

clydin commented Sep 19, 2016

Something to experiment with (that does not require modification of the CLI itself) is to add a vendor.ts file to the first position of scripts in angular-cli.json and remove the jquery and moment lines.

Potential contents of vendor.ts:

import * as moment from 'moment';
import * as jquery from 'jquery';

window['moment'] = moment;
window['jQuery'] = window['$'] = jquery;

@isaackehle
Copy link

I am interested in this feature as well, for this exact reason. Is this in process?

@alejoar
Copy link

alejoar commented Oct 5, 2016

@pgkehle the solution provided by @clydin works perfectly, although I am interested on this working out of the box too.

@isaackehle
Copy link

@alejoar I am working through this, but getting a lot of errors related now to jQuery not found, as my app uses bootstrap v4 and other modules. Curious if there is a working example.

bootstrap.js:8 Uncaught Error: Bootstrap's JavaScript requires jQuery

@filipesilva filipesilva self-assigned this Oct 9, 2016
@filipesilva
Copy link
Contributor

@pgkehle you can already use bootstrap4, see https://github.com/angular/angular-cli#global-library-installation. The problem shown in this issue is specific to how dependencies used in both scripts and inside your app interact.

@MrChoclate
Copy link
Author

@clydin Your fix does not seem to work for me in Firefox 49 but works in Chrome 53.
I ran into an issue with scrolltofixed plugin (unhelpful error message). (Works with my PR)

But I had to use $('#calendar').fullCalendar in ngAfterViewChecked and not after ngAfterViewInit (for Firefox and with my PR). So maybe I misused life cycle hooks with the scrolltofixed plugin.

Anyway, either your fix does not work with Firefox or lifecycle hooks works differently between Chrome and Firefox. Did you test your fix with Firefox? When do you use jQuery plugins? ngAfterViewInit or ngAfterViewChecked?

@maxailloud
Copy link

I have the exact same issue with almost (not the same calendar package) the same case with moment.
Definitely something weird going on here.

@filipesilva filipesilva added command: build P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful type: bug/fix and removed needs: investigation Requires some digging to determine if action is needed labels Nov 21, 2016
@filipesilva filipesilva added this to the RC1 milestone Nov 21, 2016
filipesilva added a commit to filipesilva/angular-cli that referenced this issue Jan 1, 2017
@filipesilva
Copy link
Contributor

So #3814 fixes this issue, but not by adding externals.

Rather, it fixes a bug that forced files listed as scripts to always be loaded as a string via script-loader, making them useless for imports.

@filipesilva
Copy link
Contributor

I'd like to note that, since this is NOT the externals functionality, if you want to use the global instance you will need to still declare libInstance: any (or some other type) and never import directly.

I'd prefer to not add externals because it forces people to figure out how some libs work and what they export. For some libs that's really hard to tell.

I think it's overall preferable to just have feature parity with script tags which is a much simpler concept to understand, explain and use.

filipesilva added a commit to filipesilva/angular-cli that referenced this issue Jan 4, 2017
@gregvis
Copy link

gregvis commented Jan 4, 2017

I still require externals for using Angular 2 with Electron.

For example, i'm using an npm library called 'drivelist' which calls a node 'child_process'. The only way I could get this to work with ng-serve is to make 'drivelist' external and have Electron load the module.

For ng serve, i included the external like this to work:

externals: {
'drivelist': 'commonjs '+ path.resolve(projectRoot, 'node_modules', 'drivelist'),
'electron': 'commonjs electron'

    }

Then in Electron, i'm just loading the ng serve url:

win = new BrowserWindow({width: 800, height: 600})
win.loadURL('http://localhost:4200');

@thejewdude
Copy link

I have an issue that is kind of related.
My setup:
My app uses Fullcalendar which depends on momentjs to be in global scope. I am also using moment throughout my app. Fullcalendar is added with angular-cli.json, but due to this issue I added moment to index.html with a script tag.
The issue is that ng test throws an exception due to moment not being defined. I see that the test runner is loading all the scripts defined in the angular-cli.json. Moment is not in loaded to global scope because it seems that the test runner is ignoring the index.html and any script tags defined there won't be available in the testing environment.
This issue only cropped up in newer versions of the cli (maybe as early as beta.24). Does this warrant a new issue?

@angular-automatic-lock-bot
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.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful type: bug/fix
Projects
None yet
8 participants