When using SystemJS for writing an Angular2 app I can do a
// map tells the System loader where to look for things
var map = {
'app': 'app', // 'dist',
'#angular': 'node_modules/#angular',
'rxjs': 'node_modules/rxjs'
};
to tell angular where to find things when I call a import {} from. In this case if I wanted to use RxJS now I could import { Observable } from 'rxjs/Rx'.
But what would the equivalent of this be if I were using Webpack?
Webpack does that automatically. Unless you are using code splitting.
Suppose you have:
Module A:
import {fn} "moduleB"
Module B:
export default fn
Webpack will include all the dependencies of module A (your entry), so you will be able to use fn.
Now if you use code splitting, you will need to use require.ensure
e.g:
require.ensure(["module-a", "module-b"], function(require) {
var a = require("module-a");
// ...
});
Related
If I use require to import a module the error is: webpack_require is not a function.
If I use the import statement then its function are not working and I get a type-error.
Does webpack not work with bower?
You could resolve dependency using an alias. Refer https://webpack.js.org/configuration/resolve/?_sm_au_=iVV0dsf3NTdNVrRc#resolvealias
In webpack add the following config:
resolve: {
alias: {
jQuery: path.resolve('./bower_components/jquery/dist/jquery.js'),
...
}
}
In the application wherever you need jQuery import using below line (assuming you are using CommonJS module):
var $ = require('jQuery');
Hope this helps :)
I'm working on an Angular application that integrates into a bigger one. We use RequireJs and I'm migrating to Webpack. My code depends on an external requirejs module in the format:
var x = require('foo/foo/bar');
Edit: the module is actually a script located in serverRoot/foo/foo/bar.js.
In my webpack.config.js I'm telling webpack to not bother with that module, because it's provided externally:
externals: {
'foo/foo/bar': 'foo/foo/bar'
}
This generates the following code by webpack:
/* 15 */
/***/ function(module, exports) {
module.exports = foo/foo/bar;
/***/ },
Which obviously raises an error.
So... how can I make it work?
The external library or target should expose a var to the global context, for example, using external jquery library:
externals: {
// require("jquery") is external and available
// on the global var jQuery
"jquery": "jQuery"
}
so in you case, if require('foo/foo/bar') would expose a globalFoo variable, you could set the externals:
externals: {
"globalFoo": "foo/foo/bar"
}
I'm trying to use angular-material with a ng-metadata project and I run into some issues.
I use DefinitelyTyped for angular material and the first lines are:
declare module 'angular-material' {
var _: string;
export = _;
}
In my main.ts I try to import { ngMaterial } from 'angular-material';
then bootstrap( AppComponent, [ 'ngMaterial' ] ); but all I got is:
Error:(3, 10) TS2305: Module ''angular-material'' has no exported member 'ngMaterial'.
I don't know what I am doing wrong
When being used through ES6 or TypeScript, a common pattern that Angular modules follow is that they'll use their name as the default export. For example, one of the modules in my application looks like this:
const session = angular.module("smSession", [])
.service("session", SessionService)
.component("smLogin", Login)
.config(routes)
.run(loginRedirect);
export default session.name;
The reasoning behind this is that it makes the syntax for declaring an Angular module's dependencies cleaner; for example:
import angular from "angular";
import ngAnimate from "angular-animate";
import ngMaterial from "angular-material";
import uiRouter from "angular-ui-router";
let module = angular.module("myApp", [ ngAnimate, ngMaterial, uiRouter ]);
If they instead exported the entire module, you'd have to do this:
let module = angular.module("myApp", [ ngAnimate.name, ngMaterial.name, uiRouter.name ]);
So this is why the main module declaration for angular-material looks like it does - they're simply representing the fact that all you can import from the package is that one string representing the module's name. The rest of the type definitions are ambient - you can just use the angular.material namespace anywhere in your application without having to do an import.
EDIT: To clarify, here's the actual source of the file that gets imported when you import ngMaterial:
// Should already be required, here for clarity
require('angular');
// Load Angular and dependent libs
require('angular-animate');
require('angular-aria');
// Now load Angular Material
require('./angular-material');
// Export namespace
module.exports = 'ngMaterial';
Notice that require('./angular-material') doesn't return anything - that import effectively just runs the file that sets up the Angular module behind the scenes (effectively the same sort of code as in my examples). The only thing being exported from the module is the name.
I'm trying to write a simple Angular 2 application which consumes a CommonJS Node module (Node Yelp). Angular 2 by default uses SystemJS which has the ability to load different module formats.
I have tried several different SystemJS configurations and import statements, but all of them seem to end with
SyntaxError: Unexpected token <(…)
Currently, my SystemJS configuration looks like
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
},
map: {
yelp: 'node_modules/yelp'
}
});
System.import('app/main')
.then(null, console.error.bind(console));
and my simple AppComponent.ts
import {Component} from 'angular2/core';
import Yelp from 'yelp';
#Component({
selector: 'app',
templateUrl: '/app/app.component.html'
})
export class AppComponent {
constructor(yelp: Yelp) {
console.log(yelp);
}
}
I'm still trying to wrap my head around the whole module system, so I'm not exactly sure what to change here. Any results online seem to be out dated, or not direclty related to loading CommonJS node modules with SystemJS.
I think that you could try something like that:
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
},
yeld: {
main: index.js
}
},
map: {
yelp: 'node_modules/yelp'
}
});
and
import * as Yelp from 'yelp';
The solution, as I expected, turned out to be an easy one.
Don't try roll your own System.config when using NPM packages in Angular 2
Instead, use jspm to install packages. By doing so, all of the System.config will be taken care of by jspm. In this particular case, it was as easy as
jspm install npm:yelp
Then just adding
import Yelp from 'npm:yelp#1.0.1';
to the top of my AppComponent.ts file
I really like Angular.
Having said that, I want to create a plugin in Angular that can be hosted in other websites - no matter what framework they're using. These frameworks can be Angular and it might be something else.
Surely, the latter it easier. I just add my Angular code and violla. It just works. The former is what I'm having troubles with - websites that do use Angular.
A simple setup created locally failed due to:
WARNING: Tried to load angular more than once.
Any suggestions on how I can overcome this issue ?
It sounds almost like you want to create an angular module that you may register on NPM.
In terms of the error you referenced, you may want to tweak your "loader" script. I have created a few public npm modules that use this format also with webpack to create the scripts. This is what my "loader" script looks like. It allows for script tag, commonJS, and AMD module loading.
import mooAccordionDirective from './mooAccordion.js';
import mooRepeatTranscludeModule from 'moo-utility-repeat-transclude';
(function (root, factory) {
if (typeof module !== 'undefined' && module.exports) {
// CommonJS
if (typeof angular === 'undefined') {
var angular = require('angular');
factory(angular);
module.exports = 'mooAngularAccordion';
} else {
factory(angular);
module.exports = 'mooAngularAccordion';
}
} else if (typeof define === 'function' && define.amd) {
// AMD
define(['angular'], factory);
} else {
// Global Variables
factory(root.angular);
}
}(this, function (angular) {
'use strict';
// create your angular module and do stuff
var moduleName = 'mooAngular.accordion';
var mod = angular.module(moduleName, ['mooAngular.utilityRepeatTransclude']);
mooAccordionDirective(mod);
return moduleName; // the name of your module
}));
For more reference on how I built the entire project using Webpack+AngularJS+ES6 you can view my github page for the moo-angular-accordion project.
For you to use this script it would look like:
(function (root, factory) {
if (typeof module !== 'undefined' && module.exports) {
// CommonJS also this prevents your error you are getting.
if (typeof angular === 'undefined') {
var angular = require('angular');
factory(angular);
module.exports = 'myModuleExportString';
} else {
factory(angular);
module.exports = 'myModuleExportString';
}
} else if (typeof define === 'function' && define.amd) {
// AMD
define(['angular'], factory);
} else {
// Global Variables
factory(root.angular);
}
}(this, function (angular) {
'use strict';
// create your angular module and do stuff
var moduleName = 'myModule';
var mod = angular.module(moduleName, ['otherDepModulesIfNeeded']);
mod.directive(/*... defined here ...*/);
return moduleName; // the name of your module
}));
Breakdown:
You define a IIEF which is called with this and your module function (factory) provided as arguments.
The logic checks to see if angular already exists in the global namespace (and if CommonJS support is available.
If angular exists, use it (so that it isn't defined twice), and pass that angular to your module definition (factory)
If not CommonJS, check AMD
If not AMD, load to root as a global (usable as a Script tag)
EDIT: You can also use Grunt, Gulp, or whatever build system you want to bundle your assets instead of Webpack, however the magical script above makes your module exportable in multiple formats (AMD, Script Tag, CommonJS, etc.).
#Sean Larkin's answer is correct, but for those of you using jspm and typescript, here'e what I did there.
1) Write your App module:
/// <reference path="typings/tsd.d.ts" />
import * as angular from "angular";
import modules from "./Modules"; // a simple exported array
// Create our angular module.
angular.module("module.name", modules);
2) Run this command to build a bundle:
jspm bundle-sfx App - angular app.min.js --globals "{ 'angular': 'angular' }" --minify
3) Now app.min.js is an ES5 module library easy to be loaded in a script tag or even another jspm consumer website.