问题
I use SystemJS in my Angular2 project. I use tsconfig file for TypeScript. I want to use gulp to concat and minify my code for production version. I am having an issues with concating the code: each time I try to concat files I get either \'angular\' not defined or \'system\' not defined. I tried to modify the order that I try to load my files from node modules, however I did not succeeded.
I was wondering if any of you had this issues, and found an answer to it?
Here is my gulp file:
var gulp = require(\'gulp\'),
.....
var paths = {
dist: \'dist\',
vendor: {
js: [
\'node_modules/systemjs/dist/system.src.js\',
\'node_modules/angular2/bundles/angular2.dev.js\',
\'node_modules/angular2/bundles/angular2-polyfills.js\',
\'node_modules/angular2/bundles/router.dev.js\'
...
],
css: []
},
app: {
templates: [
\'app/**/*.html\',
\'!node_modules/*.html\'
],
scripts: [
\'app/**/*.ts\',
\'app/config.ts\',
\'app/app.ts\'
]
}
};
var tsProject = ts.createProject(\'tsconfig.json\', {
out: \'Whatever.js\'
});
gulp.task(\'dev:build:templates\', function () {
return gulp.src(paths.app.templates)
.pipe(ngHtml2Js({
moduleName: \'Whatever\',
declareModule: false
}))
.pipe(concat(\"Whatever.tpls.min.js\"))
.pipe(gulp.dest(paths.dist));
});
gulp.task(\'prod:build:templates\', function () {
return gulp.src(paths.app.templates)
.pipe(minifyHtml({
empty: true,
spare: true,
quotes: true
}))
.pipe(ngHtml2Js({
moduleName: \'whatever\',
declareModule: false
}))
.pipe(concat(paths.appName + \".tpls.min.js\"))
.pipe(uglify())
.pipe(gulp.dest(paths.dist));
});
gulp.task(\'dev:build:scripts\', function () {
var tsResult = tsProject.src()
.pipe(sourcemaps.init())
.pipe(ts(tsProject));
return tsResult.js
.pipe(sourcemaps.write({
sourceRoot: \'/app\'
}))
.pipe(concat(\'whatever.js\'))
.pipe(gulp.dest(paths.dist));
});
gulp.task(\'dev:build:styles\', function () {
return gulp.src(paths.app.styles)
.pipe(sass())
.pipe(gulp.dest(paths.dist + \'/css\'));
});
gulp.task(\'dev:build:vendor\', function () {
return gulp.src(paths.vendor.js)
.pipe(concat(\'vendor.min.js\'))
.pipe(gulp.dest(paths.dist))
});
gulp.task(\'dev:build\', [
\'dev:build:vendor\',
\'dev:build:templates\',
\'dev:build:scripts\',
\'dev:build:styles\',
], function () {
});
This is how I load my files:
<script src=\"vendor.min.js\"></script>
<script src=\"Whatever.js\"></script>
<script src=\"Whatever.tpls.min.js\"></script>
And here are the erors that I am getting:
Uncaught TypeError: Unexpected anonymous System.register call.(anonymous function) @ vendor.min.js:2680load.metadata.format @ vendor.min.js:3220oldModule @ vendor.min.js:3749(anonymous function) @ vendor.min.js:2411SystemJSLoader.register @ vendor.min.js:2636(anonymous function) @ Whatever.js:2
Whatever.tpls.min.js:1 Uncaught ReferenceError: angular is not defined
回答1:
You will get " Unexpected anonymous System.register call" because the references are not being loaded in the correct order. I use JSPM to properly build my angular app for production. There are 4 parts to the process.
Part 1: Compile your typescript files
var ts = require("gulp-typescript");
var tsProject = ts.createProject("./App/tsconfig.json");
gulp.task("compile:ts", function () {
var tsResult = tsProject.src()
.pipe(ts(tsProject));
tsResult.js.pipe(gulp.dest("./wwwroot/app"));
});
Part 2: Configure config.js (to tell JSPM how to bundle your app):
System.config({
baseURL: "/",
defaultJSExtensions: true,
paths: {
"npm:*": "jspm_packages/npm/*",
"github:*": "jspm_packages/github/*",
"node_modules*": "node_modules/*"
},
map: {
'app': 'app',
'rxjs': 'node_modules/rxjs',
'@angular': 'node_modules/@angular'
},
packages: {
'app': { main: 'bootDesktop.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'@angular/common': { main: 'index.js', defaultExtension: 'js' },
'@angular/compiler': { main: 'index.js', defaultExtension: 'js' },
'@angular/core': { main: 'index.js', defaultExtension: 'js' },
'@angular/http': { main: 'index.js', defaultExtension: 'js' },
'@angular/platform-browser': { main: 'index.js', defaultExtension: 'js' },
'@angular/platform-browser-dynamic': { main: 'index.js', defaultExtension: 'js' },
'@angular/router': { main: 'index.js', defaultExtension: 'js' },
'@angular/router-deprecated': { main: 'index.js', defaultExtension: 'js' },
'@angular/testing': { main: 'index.js', defaultExtension: 'js' },
'@angular/upgrade': { main: 'index.js', defaultExtension: 'js' }
}
});
Part 3: Use gulp-jspm-build to bundle up your app (I was previously using gulp-jspm but it was causing errors, so I switched to gulp-jspm-build):
var jspm = require('gulp-jspm-build');
gulp.task("jspm_bundle", function () {
return jspm({
bundleOptions: {
minify: true,
mangle: false
},
bundleSfx: true,
bundles: [
{ src: './wwwroot/app/appBoot.js', dst: 'boot.bundle.min.js' }
]
})
.pipe(gulp.dest('./wwwroot/js-temp'));
});
//this will create a file called boot.bundle.min.js
//note I have set jspm to create a self-executing bundle
//I put mangle to false because mangling was causing errors
4: Now concat all your already minified assets:
gulp.task("min:js", ["jspm_bundle"], function () {
//this only concats boot.bundle.min.js
//and dependencies.min.js which has already been minified such as es6-shim.js
var files = [
"./wwwroot/js-temp/dependencies.min.js",
"./wwwroot/js-temp/boot.bundle.min.js"
];
return gulp.src(files)
.pipe(concat("boot.bundle.min.js"))
.pipe(gulp.dest("./wwwroot/js"));
});
Finally, put one nice tidy script reference into your index.html:
<script src="~/js/boot.bundle.min.js"> </script>
UPDATE: Revised config.js to conform to a Angular 2.0-rc.0 appp
UPDATE 2: tsconfig.json looks like this:
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "commonjs",
"moduleResolution": "node",
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"declaration": false,
"noLib": false,
"target": "es5",
"outDir": "wwwroot/app/"
},
"exclude": [
"node_modules",
"wwwroot"
]
}
回答2:
You can use SystemJS Builder
as easy as this
var path = require("path");
var Builder = require('systemjs-builder');
// optional constructor options
// sets the baseURL and loads the configuration file
var builder = new Builder('path/to/baseURL', 'path/to/system/config-file.js');
builder
.bundle('local/module.js', 'outfile.js')
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.log('Build error');
console.log(err);
});
you can look at the full setup in my starter project
回答3:
I think we found the root cause of this. Honestly, I have been there before so the way I trace this type of issue are
- Check if angular & systemjs are loaded beforehand.
- Check if they are really loaded. no 404 surprise. (It sounds stupid but shit happens)
- If you bundle libraries as vender.js make sure they are bundle in correct sequence. Check the output file and see if they are concat as the way you expect.
来源:https://stackoverflow.com/questions/34614743/how-to-prepare-release-version-with-systemjs-and-gulp