I have a javascript bundle that's made available without a '.js' extension, so when SystemJS tries to import bundles/main.js it throws a 404.
I've tried to establish that these bundles have no extension by adding a defaultExtension: '', but to no avail.
Here's the System.import line
System.import("bundles/main")
and my config.js
System.config({
baseURL: "/",
defaultJSExtensions: true,
transpiler: "typescript",
paths: {
"github:*": "jspm_packages/github/*",
"npm:*": "jspm_packages/npm/*"
},
packages: {
'bundles/main': {
format: 'js',
defaultExtension: ''
}
},
meta: {
"Scripts/vendor/*": {
"format": "global"
},
...
EDIT
Note that the issue is that SystemJS is looking for bundles/main.js ... NOT bundles/main as it should be
First off - thanks for your help! I've built a web app using Angular 2 and am in the final process of launching in production, but am experiencing an error in bundling with Gulp. There seems to be a lot of documentation around the specific Typeerror I'm experiencing, but nothing that I've seen really matches my use case and position in the process.
Specifically, the actual bundling process itself returns no errors when running the following command:
sudo gulp
However, when validating whether the code can run on my localhost, the following error is returned:
Uncaught TypeError: Cannot read property 'prototype' of undefined
and the file where this error is referenced is app.min.js, which is the output file of my wholly bundled code.
After debugging the issue further, from what I can tell, there's potentially some disconnect in how modules are being evaluated, but I can't seem to put a thumb on the root cause of the issue, or a solution to the issue. That's where I could use the community's help - figuring out how to address the issue where 'prototype' cannot be read.
gulpfile.js:
const gulp = require('gulp');
const del = require('del');
const cleanCSS = require('gulp-clean-css');
const concat = require('gulp-concat');
const liveServer = require('gulp-live-server');
const plumber = require('gulp-plumber');
const runSequence = require('run-sequence');
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');
const sysBuilder = require('systemjs-builder');
const tslint = require('gulp-tslint');
const tsc = require('gulp-typescript');
const uglify = require('gulp-uglify');
const tsconfig = require('tsconfig-glob');
const tscConfig = require('./tsconfig.json')
// Development
gulp.task("devmin", function () {
return gulp.src([
'wwwroot/js/jquery.js',
'node_modules/core-js/client/shim.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/reflect-metadata/Reflect.js',
'wwwroot/js/toastr.js',
'wwwroot/js/moment.js',
'wwwroot/js/typescript.js',
])
.pipe(concat('site.min.js'))
.pipe(uglify())
.pipe(gulp.dest('wwwroot/js'));
});
// Clean the distribution directory
gulp.task('clean:dist', function() {
return del('wwwroot/dist/*');
});
// Clean the JavaScript distribution directory
gulp.task('clean:dist:js', function() {
return del('wwwroot/dist/js/*');
});
// Clean the CSS Distribution directory
gulp.task('clean:dist:css', function() {
return del('wwwroot/dist/css/*');
});
// Clean library directory
gulp.task('clean:lib', function () {
return del('wwwroot/lib/**/*');
});
// Compile TypeScript to JS
gulp.task('compile:ts', function () {
return gulp
.src(tscConfig.filesGlob)
.pipe(plumber({
errorHandler: function (err) {
console.error('>>> [tsc] Typescript compilation failed'.bold.green);
this.emit('end');
}}))
.pipe(sourcemaps.init())
.pipe(tsc(tscConfig.compilerOptions))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('wwwroot/dist/app'));
});
// Generate SystemJS-based builds
gulp.task('bundle:js', function() {
var builder = new sysBuilder('wwwroot', 'wwwroot/systemjs.config.js');
console.log("-----------------------------Start");
return builder.buildStatic('app', 'wwwroot/dist/js/app.min.js')
.then(function () {
console.log("-----------------------------Deleting");
return del(['wwwroot/dist/js/**/*', '!wwwroot/dist/js/app.min.js']);
})
.catch(function(err) {
console.error('>>> [systemjs-builder] Bundling failed'.bold.green, err);
});
});
// Minify JS bundle
gulp.task('minify:js', function() {
return gulp
.src('wwwroot/dist/js/app.min.js')
.pipe(uglify())
.pipe(gulp.dest('wwwroot/dist/js'));
});
gulp.task('compile:sass', function() {
// concat and minify global scss files
gulp
.src('wwwroot/css/global/*.scss')
.pipe(plumber({
errorHandler: function (err) {
console.error('>>> [sass] Sass global style compilation failed'.bold.green);
this.emit('end');
}}))
.pipe(sourcemaps.init())
.pipe(sass({ errLogToConsole: true }))
.pipe(concat('styles.min.css'))
// .pipe(cleanCSS())
.pipe(sourcemaps.write())
.pipe(gulp.dest('wwwroot/dist/css/global'));
// minify component specific scss files
gulp
.src('wwwroot/css/*.scss')
.pipe(plumber({
errorHandler: function (err) {
console.error('>>> [sass] Sass component style compilation failed'.bold.green);
this.emit('end');
}}))
.pipe(sourcemaps.init())
.pipe(sass({ errLogToConsole: true }))
// .pipe(cleanCSS())
.pipe(sourcemaps.write())
.pipe(gulp.dest('wwwroot/dist/css/component'));
});
// Concat and minify CSS
gulp.task('minify:css', function() {
// concat and minify global css files
gulp
.src('wwwroot/css/*.css')
.pipe(concat('styles.min.css'))
.pipe(cleanCSS())
.pipe(gulp.dest('wwwroot/dist/css'));
// minify component css files
gulp
.src('wwwroot/css/component/*.css')
.pipe(cleanCSS())
.pipe(gulp.dest('wwwroot/dist/css/component'));
});
// Copy dependencies
gulp.task('copy:libs', function() {
gulp.src([
'node_modules/rxjs/**/*'
])
.pipe(gulp.dest('wwwroot/lib/js/rxjs'));
gulp.src([
'./node_modules/reflect-metadata/Reflect.js',
'./node_modules/zone.js/dist/zone.js',
'./node_modules/core-js/client/shim.js',
'.node_modules/systemjs/dist/system.src.js',
'./node_modules/bootstrap/dist/js/bootstrap.js',
'./node_modules/jquery/dist/jquery.js',
'./node_modules/moment/moment.js',
'./node_modules/es6-promise/dist/es6-promise.js',
'./node_modules/typescript/lib/typescript.js',
'./node_modules/systemjs/dist/system.src.js',
'./node_modules/toastr/package/toastr.js'
])
.pipe(gulp.dest('wwwroot/lib/js'));
gulp.src([
'./node_modules/jquery/dist/jquery.min.js',
'./node_modules/bootstrap/dist/js/bootstrap.min.js',
'./node_modules/es6-promise/dist/es6-promise.min.js',
'./node_modules/toastr/toastr.js',
'./node_modules/moment/min/moment.min.js',
'./node_modules/angular-in-memory-web-api/dist/index.js',
'./wwwroot/systemjs.config.js'
])
.pipe(concat('vendors.min.js'))
.pipe(uglify())
.pipe(gulp.dest('wwwroot/lib/js'));
// copy source maps
gulp.src([
'./node_modules/es6-shim/es6-shim.map',
'./node_modules/reflect-metadata/Reflect.js.map',
'./node_modules/systemjs/dist/system-polyfills.js.map'
]).pipe(gulp.dest('wwwroot/lib/js'));
gulp.src([
'.node_modules/bootstrap/dist/css/bootstrap.*',
'./node_modules/bootstrap-toggle/css/bootstrap-toggle.css',
'./node_modules/bootstrap/dist/css/bootstrap-theme.css',
'./node_modules/bootstrap/dist/css/bootstrap-theme.css.map',
'./node_modules/bootstrap-social/bootstrap-social.css',
'./node_modules/font-awesome/css/font-awesome.css.map',
'./node_modules/font-awesome/css/font-awesome.css',
'./node_modules/glyphicons-halflings/css/glyphicons-halflings.css.map',
'./node_modules/glyphicons-halflings/css/glyphicons-halflings.css',
'./node_modules/toastr/package/toastr.css',
'./node_modules/toastr/package/toastr.css',
]).pipe(gulp.dest('wwwroot/lib/css'));
gulp.src([
"./node_modules/font-awesome/fonts/FontAwesome.otf",
"./node_modules/font-awesome/fonts/fontawesome-webfont.eot",
"./node_modules/font-awesome/fonts/fontawesome-webfont.svg",
"./node_modules/font-awesome/fonts/fontawesome-webfont.ttf",
"./node_modules/font-awesome/fonts/fontawesome-webfont.woff",
"./node_modules/font-awesome/fonts/fontawesome-webfont.woff2",
"./node_modules/bootstrap/fonts/glyphicons-halflings-regular.eot",
"./node_modules/bootstrap/fonts/glyphicons-halflings-regular.svg",
"./node_modules/bootstrap/fonts/glyphicons-halflings-regular.ttf",
"./node_modules/bootstrap/fonts/glyphicons-halflings-regular.woff",
"./node_modules/bootstrap/fonts/glyphicons-halflings-regular.woff2"
]).pipe(gulp.dest('wwwroot/dist/fonts'));
gulp.src(['./node_modules/angular-in-memory-web-api/**/*']).pipe(gulp.dest('wwwroot/lib/js/angular-in-memory-web-api'));
// handle all angular
return gulp.src(['node_modules/#angular/**/*'])
.pipe(gulp.dest('wwwroot/lib/js/#angular'));
});
// Copy static assets
gulp.task('copy:assets', function() {
return gulp.src(
[
'*.json',
'*.html',
'*.css',
'!*.ts',
'!*.scss'
],
{ base: '' })
.pipe(gulp.dest('wwwroot/dist'))
});
// Update the tsconfig files based on the glob pattern
gulp.task('tsconfig-glob', function() {
return tsconfig({
configPath: '.',
indent: 2
});
});
// Watch the source files for changes, then trigger recompilation
gulp.task('watch:src', function() {
// gulp.watch('src/**/*.ts', ['scripts']);
// gulp.watch('src/**/*.scss', ['styles']);
gulp.watch('./**/*.ts', ['scripts']);
gulp.watch('./**/*.scss', ['styles']);
});
gulp.task('test', ['compile:specs'], function() {
// gulp.watch('src/**/*.ts', ['compile:specs']);
gulp.watch('./**/*.ts', ['compile:specs']);
});
gulp.task('lint', ['lint:sass']);
// gulp.task('clean', ['clean:dist:js', 'clean:dist:css', 'clean:lib']);
gulp.task('copy', function(callback) {
// runSequence('clean:lib', 'copy:libs', callback);
runSequence('copy:libs', callback);
});
gulp.task('scripts', function(callback) {
// runSequence(['clean:dist:js'], 'compile:ts', 'bundle:js', 'minify:js', callback);
runSequence('compile:ts', 'bundle:js', 'minify:js', callback);
});
gulp.task('styles', function(callback) {
// runSequence(['clean:dist:css'], ['compile:sass', 'minify:css'], callback);
runSequence(['compile:sass', 'minify:css'], callback);
});
gulp.task('build', function(callback) {
runSequence('copy', 'scripts', 'styles', callback);
});
gulp.task('buildnocopy', function(callback) {
runSequence('scripts', 'styles', callback);
});
gulp.task('default', function(callback) {
runSequence('build', callback);
});
systemjs.config.js:
// map tells the System loader where to look for things
var map = {
'app': 'dist/app',
'rxjs': 'lib/js/rxjs',
'#angular': 'lib/js/#angular',
'zone.js': 'lib/js/zone.js',
'moment': 'lib/js/moment',
'angular-in-memory-web-api': 'lib/js/angular-in-memory-web-api',
'typescript': 'lib/js/typescript',
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'zone.js': { main: 'zone', defaultExtension: 'js' },
'symbol-observable': { main: 'index.js', defaultExtension: 'js' },
'angular-localstorage': { defaultExtension: "js"},
"angular-in-memory-web-api": { main: "index.js", defaultExtension: "js" },
'moment': { defaultExtension: 'js' }
};
var packageNames = [
'#angular/common',
'#angular/compiler',
'#angular/core',
'#angular/forms',
'#angular/http',
'#angular/platform-browser',
'#angular/platform-browser-dynamic',
'#angular/router',
'#angular/testing',
'#angular/upgrade',
];
// add package entries for angular packages in the form '#angular/common': { main: 'index.js', defaultExtension: 'js' }
packageNames.forEach(function(pkgName) {
packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});
System.config({
map: map,
packages: packages
});
tsconfig.json:
{
"compileOnSave": true,
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": true,
"module": "system",
"moduleResolution": "node",
"rootDir": "wwwroot",
"outDir": "wwwroot/dist",
"sourceMap": true,
"target": "ES5",
"noImplicitAny": false,
"noEmitOnError": true,
"suppressImplicitAnyIndexErrors": true
},
"exclude": [
"wwwroot/node_modules",
"node_modules",
"typings",
"wwwroot/lib"
],
"filesGlob": [
"wwwroot/app/**/**/*.ts",
"typings/*.d.ts"
]
}
Please let me know if I need to provide any more documentation. Thanks!
I know there was a point where the minification/uglification of Angular 2 with gulp-uglify was broken.
Try removing the uglify step and see if that helps your case.
After installing https://github.com/halt-hammerzeit/libphonenumber-js using npm and updating my systemjs.config.ts to include
map:{
...
'libphonenumber-js': 'node_modules/libphonenumber-js'
},
packages: {
...
'libphonenumber-js': {
main: './custom.es6.js',
defaultExtension: 'js'
}
},
and attempting to use
import { parse, format, asYouType } from 'libphonenumber-js';
in my #Directive, I'm stuck with
Cannot find module 'libphonenumber-js'
How on earth am I supposed to wire this library into my app?
EDIT:
Directory layout:
websiteName
websiteName/index.html
websiteName/node_modules
websiteName/node_modules/libphonenumber-js
websiteName/app
websiteName/app/systemjs.config.ts
Index.html contains:
<script src="/app/systemjs.config.js"></script>
<script>
System.import('app').catch(function (err) { console.error(err); });
</script>
systemjs.config.ts contains:
declare var System: any;
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// other references
'libphonenumber-js': 'npm:libphonenumber-js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
// other references
'libphonenumber-js': {
main: './bundle/libphonenumber-js.min.js',
defaultExtension: 'js'
}
}
});
})(this);
Your package configuration is incorrect. It needs to point at the source file for libphonenumber-js. Need to update the references to match your project structure.
Try this:
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': './node_modules'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// other references
'libphonenumber-js': 'npm:libphonenumber-js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
// other references
'libphonenumber-js': {
main: 'libphonenumber-js.min',
defaultExtension: 'js'
}
}
});
})(this);
I am having trouble with SystemJS.
I have a typical Angular2 application written in Typescript.
I am trying to bundle all my application .js into a single file to optimize load time.
The bundle is created by gulp using systemjs-builder like this :
gulpfile.js
paths.compiledTs = "./wwwroot/app";
gulp.task('bundle:app', function (done) {
var builder = new Builder("/", './systemjs.config.js');
var builderConfig = {
normalize: true,
minify: true,
mangle: true,
runtime: false
};
builder.bundle(paths.compiledTs + '/main.js', paths.compiledTs + '/middleware-app.js', builderConfig)
.then(function () {
done();
})
.catch(function (err) {
console.log(err);
done();
});
});
The bundle is loaded though script tag. It works correcly as a call to System.defined in the browser console shows my modules :
System.defined
System.defined(picture)
Here is my systemjs.config.js. If I understand things correctly, an import to "app" should resolve to wwwroot/app/main.ts, then to the bundle file through the "bundles" parameter.
systemjs.config.js
/**
* System configuration
*/
(function (global) {
// map tells the System loader where to look for things
var map = {
'app': 'wwwroot/app',
'#angular': 'wwwroot/lib/#angular'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main:'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'lodash': { defaultExtension: 'js' },
'moment': { defaultExtension: 'js' },
'pikaday': { defaultExtension: 'js' },
'ng2-translate': { defaultExtension: 'js' },
};
var ngPackageNames = [
'common',
'compiler',
'core',
'forms',
'http',
'platform-browser',
'platform-browser-dynamic',
'router'
];
// Individual files (~300 requests):
function packNgIndex(pkgName) {
packages['#angular/' + pkgName] = { main: 'index.js', defaultExtension: 'js' };
}
// Bundled (~40 requests):
function packNgUmd(pkgName) {
packages['#angular/' + pkgName] = { main: 'bundles/' + pkgName + '.umd.min.js', defaultExtension: 'js' };
}
// Most environments should use UMD; some (Karma) need the individual index files
var setNgPackageConfig = System.packageWithIndex ? packNgIndex : packNgUmd;
// Add package entries for angular packages
ngPackageNames.forEach(setNgPackageConfig);
var config = {
defaultJSExtensions: true,
baseURL: global.baseUrl,
paths: {
"lodash": "wwwroot/lib/lodash.min.js",
"moment": "wwwroot/lib/moment.min.js",
"pikaday": "wwwroot/lib/pikaday.js"
},
map: map,
packages: packages,
meta: {
pikaday: {
deps: ['moment']
},
'angular2/*': {
build: false
},
'rxjs/*': {
build: false
},
'ng2-translate/*': {
build: false
}
},
bundles: {
"wwwroot/lib/bundles/rxjs.min.js": [
"rxjs/*",
"rxjs/operator/*",
"rxjs/observable/*",
"rxjs/add/operator/*",
"rxjs/add/observable/*",
"rxjs/util/*"
],
"wwwroot/lib/bundles/ng2-translate.min.js": [
"ng2-translate/*"
],
"wwwroot/app/middleware-app.js": [
"app/*",
"app/common/busy-indicator/*",
"app/common/config/*",
"app/common/date-picker/*",
"app/common/dialog/*",
"app/common/guards/*",
"app/common/interface/*",
"app/common/login/*",
"app/common/models/*",
"app/common/pagination/*",
"app/common/services/*",
"app/common/storage/*",
"app/i18n/*",
"app/layout/*",
"app/pages/authentication/*",
"app/pages/logs/*",
"app/pages/monitoring/*",
"app/pages/not-found/*",
"app/pages/referentials/*",
"app/pages/reports/*"
]
}
};
System.config(config);
})(this);
However once I attempt to import my entry point from index.html, nothing happens (meaning I don't enter my then callback or my catch block). Here is an extract of my index :
<script src="#Href("~/wwwroot/app/middleware-app.js")"></script>
<script type="text/javascript">
System.import('app')
.then(app => {
console.log("never entered");
var endpoint = '#endpointUrl';
var version = '#Html.Version()';
var production = #Html.IsProductionEnabled();
app.run(endpoint, version, production);
})
.catch(function (err) {
console.log("never entered as well");
console.error(err);
});
</script>
I have tried various things like using bundleStatic instead, importing app/main.js, changing the bundling options.
Thank you for any help you can provide.
I assume that you are quite advanced and you have good angular2 understanding.
I had similar issue with #angular/upgrade component. After serious headache, I have found out that some of the error messages are lost inside angular2 (even in currently stable package).
The possible source of error can be inside #angular/compiler. The RuntimeCompiler.compileComponents() is losing messages from CompileMetadataResolver.getNgModuleMetadata(). Simple, yet not ideal solution is to wrap call to getNgModuleMetadata in try-catch block.
Solution when you are using bundled compiler and angular 2.0.0:
compiler.umd.js:line 16799
Change this:
RuntimeCompiler.prototype._compileComponents = function (mainModule, isSync) {
var _this = this;
var templates = new Set();
var loadingPromises = [];
var ngModule = this._metadataResolver.getNgModuleMetadata(mainModule);
ngModule.transitiveModule.modules.forEach(function (localModuleMeta) {
...
to:
RuntimeCompiler.prototype._compileComponents = function (mainModule, isSync) {
var _this = this;
var templates = new Set();
var loadingPromises = [];
try {
var ngModule = this._metadataResolver.getNgModuleMetadata(mainModule);
} catch(e) {
console.log(e);
throw e;
}
ngModule.transitiveModule.modules.forEach(function (localModuleMeta) {
...
Obviously, this is not ideal solution, but I was able to find out that one of my modules had circular dependency (which was causing undefined instead of valid service inside NgModule.import).
How do add new packages I just downloaded from npm to my Angular 2 components using SystemJS and using this system.config.js file. The code bellow was generated for me by a starter package.
I have tried to put links to the modules in the map and packages section of this file but it doesn't seem to work. All I want to know is how can I take a library such as underscore js located in my node_modules and input it into this file so I can easily import the file in my typescript angular components.
var isPublic = typeof window != "undefined";
(function(global) {
var map = {
'app': 'client', // 'dist',
'#angular': (isPublic)? '#angular' : 'node_modules/#angular',
'#angular/router': (isPublic)? '#angular/router' : 'node_modules/#angular/router',
'angular2-in-memory-web-api': (isPublic)? 'angular2-in-memory-web-api' : 'node_modules/angular2-in-memory-web-api',
'rxjs': (isPublic)? 'rxjs' : 'node_modules/rxjs',
'ng-semantic': (isPublic)? 'ng-semantic' : 'node_modules/ng-semantic'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'ng2-ace': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
'ng-semantic': { main: 'ng-semantic', defaultExtension: 'js' }
};
var ngPackageNames = [
'common',
'compiler',
'core',
'http',
'forms',
'platform-browser',
'platform-browser-dynamic',
'router-deprecated',
'upgrade',
'ng2-ace'
];
// Individual files (~300 requests):x
function packIndex(pkgName) {
packages['#angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
}
// Bundled (~40 requests):
function packUmd(pkgName) {
packages['#angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
}
packages['#angular/router'] = { main: 'index.js', defaultExtension: 'js' };
var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
// Add package entries for angular packages
ngPackageNames.forEach(setPackageConfig);
var config = {
map: map,
packages: packages
};
System.config(config);
})(this);
Just include this file into your main HTML file (index.html):
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script> <-----
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
Edit
You need to install the library using npm and configure it within the SystemJS configuration:
System.config({
(...)
map: {
underscore: 'node_modules/underscore/underscore.js'
}
});
See this question (similar but for Lodash):
Importing lodash into app.ts file
Don't forget to install typings for the Underscore library.