如何使用 SystemJS 和 Gulp 准备发布版本?
How to prepare release version with SystemJS and Gulp?
我在 Angular2 项目中使用 SystemJS。我为 TypeScript 使用 tsconfig 文件。我想使用 gulp 来连接和缩小我的生产版本代码。我在连接代码时遇到问题:每次尝试连接文件时,我都会得到 'angular' not defined 或 'system' not defined。我试图修改我尝试从节点模块加载文件的顺序,但是我没有成功。
我想知道你们中是否有人遇到过这个问题,并找到了答案?
这是我的 gulp 文件:
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 () {
});
这是我加载文件的方式:
<script src="vendor.min.js"></script>
<script src="Whatever.js"></script>
<script src="Whatever.tpls.min.js"></script>
这是我遇到的错误:
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
我想我们找到了这个问题的根本原因。老实说,我以前去过那里,所以我追踪这类问题的方式是
- 检查是否预先加载了 angular 和 systemjs。
- 检查它们是否真的加载了。没有 404 惊喜。 (这听起来很愚蠢,但狗屎发生了)
- 如果您将库捆绑为 vender.js,请确保它们以正确的顺序捆绑。检查输出文件,看看它们是否按照您期望的方式连接。
您将收到“意外的匿名 System.register 调用”,因为未按正确的顺序加载引用。我使用 JSPM 正确构建我的 angular 应用程序以用于生产。该过程有 4 个部分。
第 1 部分:编译您的打字稿文件
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"));
});
第 2 部分:配置 config.js(告诉 JSPM 如何捆绑您的应用程序):
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' }
}
});
第 3 部分:使用 gulp-jspm-build 捆绑您的应用程序(我之前使用 gulp-jspm 但它导致错误,所以我切换到 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:现在连接所有已经缩小的资产:
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"));
});
最后,将一个整洁的脚本参考放入您的 index.html:
<script src="~/js/boot.bundle.min.js"> </script>
这种方法的一个很好的特性是你的捆绑应用程序将只包含你导入语句中实际引用的资产(如果你不需要它,jspm 不会捆绑它)。
更新:修订 config.js 以符合 Angular 2.0-rc.0 appp
更新 2:tsconfig.json 看起来像这样:
{
"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"
]
}
您可以使用SystemJS Builder
就这么简单
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);
});
你可以在我的 starter project
中查看完整设置
我在 Angular2 项目中使用 SystemJS。我为 TypeScript 使用 tsconfig 文件。我想使用 gulp 来连接和缩小我的生产版本代码。我在连接代码时遇到问题:每次尝试连接文件时,我都会得到 'angular' not defined 或 'system' not defined。我试图修改我尝试从节点模块加载文件的顺序,但是我没有成功。
我想知道你们中是否有人遇到过这个问题,并找到了答案?
这是我的 gulp 文件:
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 () {
});
这是我加载文件的方式:
<script src="vendor.min.js"></script>
<script src="Whatever.js"></script>
<script src="Whatever.tpls.min.js"></script>
这是我遇到的错误:
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
我想我们找到了这个问题的根本原因。老实说,我以前去过那里,所以我追踪这类问题的方式是
- 检查是否预先加载了 angular 和 systemjs。
- 检查它们是否真的加载了。没有 404 惊喜。 (这听起来很愚蠢,但狗屎发生了)
- 如果您将库捆绑为 vender.js,请确保它们以正确的顺序捆绑。检查输出文件,看看它们是否按照您期望的方式连接。
您将收到“意外的匿名 System.register 调用”,因为未按正确的顺序加载引用。我使用 JSPM 正确构建我的 angular 应用程序以用于生产。该过程有 4 个部分。
第 1 部分:编译您的打字稿文件
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"));
});
第 2 部分:配置 config.js(告诉 JSPM 如何捆绑您的应用程序):
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' }
}
});
第 3 部分:使用 gulp-jspm-build 捆绑您的应用程序(我之前使用 gulp-jspm 但它导致错误,所以我切换到 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:现在连接所有已经缩小的资产:
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"));
});
最后,将一个整洁的脚本参考放入您的 index.html:
<script src="~/js/boot.bundle.min.js"> </script>
更新:修订 config.js 以符合 Angular 2.0-rc.0 appp
更新 2:tsconfig.json 看起来像这样:
{
"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"
]
}
您可以使用SystemJS Builder
就这么简单
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);
});
你可以在我的 starter project
中查看完整设置