Angular 2 使用 SystemJS 部署并且 Gulp 太重了
Angular 2 deploy with SystemJS and Gulp is too heavy
我已经使用 Angular 开发了一段时间,但我只是从 Angular 2 开始,在完成 Angular 2 教程的快速入门之后,我想尝试在生产模式下在服务器中开发完成的应用程序。
我没有使用 SystemJS 的经验,也没有 Gulp,所以我花了一段时间,但我终于设法让它工作了。现在我有 2 个问题:
对于一个 Hello World 应用程序来说,它真的很重,大约 20MB,因为我不得不从 Angular 2 个库下载很多文件。我的猜测是我真的不需要那么多,但是尽管我只从 @angular/core 和 @angular/platform-browser-dynamic 开始,它们是我的应用程序 ts 文件中引用的那些,angular 一直在抛出部署中的错误消息,直到我包含整个@angular 库。
另一方面,当我 运行 应用程序时,我再次看到正在下载许多单个文件,这不是我想要的。必须有一种方法可以只下载一个包含所有库的(缩小的)文件(一个包?),但我不知道该怎么做。
任何人都可以帮助我吗?
这是我的主要配置文件。
system.config.js
(function(global) {
// map tells the System loader where to look for things
var map = {
'app': 'app', // 'dist',
'@angular': 'lib/@angular',
'rxjs': 'lib/rxjs'
};
// 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' }
};
var ngPackageNames = [
'common',
'compiler',
'core',
'http',
'platform-browser',
'platform-browser-dynamic'
];
// Individual files (~300 requests):
function packIndex(pkgName) {
packages['@angular/' + pkgName] = { main: 'index.js', defaultExtension: 'js' };
}
// Add package entries for angular packages
ngPackageNames.forEach(packIndex);
var config = {
map: map,
packages: packages
};
System.config(config);
})(this);
index.html
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="./css/styles.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="lib/shim.min.js"></script>
<script src="lib/zone.js"></script>
<script src="lib/Reflect.js"></script>
<script src="lib/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
gulpfile.js
var gulp = require('gulp');
var ts = require('gulp-typescript');
const babel = require('gulp-babel');
var tsProject = ts.createProject('tsconfig.json');
gulp.task('babel-dp', ['resources', 'babel']);
gulp.task('ts-dp', ['resources', 'ts']);
gulp.task('resources', () => {
gulp.src([
'node_modules/core-js/client/shim.min.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/reflect-metadata/Reflect.js',
'node_modules/systemjs/dist/system.src.js'
]).pipe(gulp.dest('web/lib'));
gulp.src([
'node_modules/@angular/**/*',
]).pipe(gulp.dest('web/lib/@angular'));
gulp.src([
'node_modules/rxjs/**/*',
]).pipe(gulp.dest('web/lib/rxjs'));
gulp.src([
'app/**/*.js'
]).pipe(gulp.dest('web/app'));
gulp.src([
'styles.css'
]).pipe(gulp.dest('web/css'));
gulp.src([
'index.html',
'systemjs.config.js',
'favicon.ico'
]).pipe(gulp.dest('web'));
});
gulp.task('babel', () => {
return gulp.src([
'app/**/*.ts'
])
.pipe(babel({presets: ['es2015']}))
.pipe(gulp.dest('web/js'));
});
gulp.task('ts', function(done) {
var tsResult = tsProject.src([
'app/**/*.ts'
])
.pipe(ts(tsProject));
return tsResult.js.pipe(gulp.dest('web/js'));
});
如果您需要任何其他文件,请告诉我。
非常感谢!
更新
我刚刚发现我可以使用@angular 中的umd.min.js 文件而不是单个js 文件。这是一些东西,从 20 到 5MB,但当 Angular 1 的缩小版本小于 1MB 时,看起来仍然很多。
另一方面,即使我使用了这些 umd.min.js 个文件,chrome 在加载应用程序时仍然在下载单个文件。
更新 2
我设法按照评论中的建议使用 systemjs-builder 创建了一个捆绑文件。现在我有一个包含我所有应用程序代码的文件 bundle.app.js,我的 index.html 现在看起来像这样
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="css/styles.css">
<!-- 1. Load libraries -->
<script src="app/bundle.app.js"> </script>
<!-- Polyfill(s) for older browsers -->
<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>
System.import('app').catch(function(err) { console.error(err); });
</script>
</head>
<!-- 2. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
但现在 chrome 找不到在 html 中导入的 js:shim.min.js、zone.js、Reflect.js 和 system.src.js。
我在 systemjs.config.js 中添加了一行以包含 node_modules 以防万一,但我认为没有必要。无论如何,它也不起作用。这些导入不应该已经包含在捆绑包中了吗?
关于捆绑多个文件/单个文件中的库,您可以使用 gulp 任务。
这里有一些可以帮助您入门的东西。一定要明白不同线条的意思,可能会发生,你必须改变一些小部分来反映你的需要。
const gulp = require('gulp');
const path = require('path');
const runSequence = require('run-sequence');
const paths = require('../paths');
gulp.task('bundle', cb => {
runSequence(
'bundle:app',
'bundle:vendor',
cb
);
});
const app = 'app/**/*.js';
const specs = 'app/**/*.spec.js';
gulp.task('bundle:app', () => {
const appModules = `[${app}] - [${specs}]`; // except specs
return bundle(appModules, paths.dst + '/bundle.app.js', { baseUrl: paths.dst });
});
gulp.task('bundle:vendor', () => {
// build app and remove the app code - this leaves only 3rd party dependencies
const dstApp = path.join(paths.dst, app);
const dstSpecs = path.join(paths.dst, specs);
const vendorModules = `${dstApp} - [${dstApp}]`;
return bundle(vendorModules, paths.dst + '/bundle.vendor.js');
});
function bundle(src, dst, opt) {
const bundleOptions = Object.assign({
baseUrl: '.',
minify: false,
sourceMaps: false,
lowResSourceMaps: false, // mapping granularity is per-line instead of per-character
}, opt);
const Builder = require('systemjs-builder');
const builder = new Builder(bundleOptions.baseUrl, paths.src + '/systemjs.config.js');
return builder.bundle(src, dst, bundleOptions);
}
缩小是额外的步骤,但 gulp-minify 或 gulp-uglify 值得一看。
好的,我终于有了一个工作配置,所以我会把所有需要的文件复制到这里,以防有人觉得有用。
index.html
<html>
<head>
<title>Angular 2 QuickStart Deploy</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="css/styles.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="lib/shim.min.js"></script>
<script src="lib/zone.js"></script>
<script src="lib/Reflect.js"></script>
<script src="lib/system.src.js"></script>
</head>
<!-- 2. Display the application -->
<body>
<my-app>Loading...</my-app>
<!-- application bundle -->
<script src="app/bundle.app.js"></script>
</body>
</html>
gulpfile.js
const gulp = require('gulp');
const ts = require('gulp-typescript');
const babel = require('gulp-babel');
const Builder = require('systemjs-builder');
// systemjs-builder
const builder = new Builder('.', 'systemjs.config.js');
// typescript transpiler
var tsProject = ts.createProject('tsconfig.json');
gulp.task('babel-dp', ['resources', 'babel']);
gulp.task('ts-dp', ['resources', 'ts']);
gulp.task('bundle:app', () => {
builder.buildStatic('app/*.js', 'web/app/bundle.app.js')
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.log('error ' + err);
})
})
gulp.task('resources', () => {
gulp.src([
'node_modules/core-js/client/shim.min.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/reflect-metadata/Reflect.js',
'node_modules/systemjs/dist/system.src.js'
]).pipe(gulp.dest('web/lib'));
gulp.src([
'styles.css'
]).pipe(gulp.dest('web/css'));
gulp.src([
'index.html',
'favicon.ico'
]).pipe(gulp.dest('web'));
});
gulp.task('babel', () => {
return gulp.src([
'app/**/*.ts'
])
.pipe(babel({presets: ['es2015']}))
.pipe(gulp.dest('web/js'));
});
gulp.task('ts', function(done) {
var tsResult = tsProject.src([
'app/**/*.ts'
])
.pipe(ts(tsProject));
//return tsResult.js.pipe(gulp.dest('web/js'));
return tsResult.js.pipe(gulp.dest('app/js'));
});
其余文件没有改变。
这里对我来说要点是使用 systemjs-builder 创建包(感谢@Thorsten 的提示)和在 index.html.
中使用包
我已经使用 Angular 开发了一段时间,但我只是从 Angular 2 开始,在完成 Angular 2 教程的快速入门之后,我想尝试在生产模式下在服务器中开发完成的应用程序。
我没有使用 SystemJS 的经验,也没有 Gulp,所以我花了一段时间,但我终于设法让它工作了。现在我有 2 个问题:
对于一个 Hello World 应用程序来说,它真的很重,大约 20MB,因为我不得不从 Angular 2 个库下载很多文件。我的猜测是我真的不需要那么多,但是尽管我只从 @angular/core 和 @angular/platform-browser-dynamic 开始,它们是我的应用程序 ts 文件中引用的那些,angular 一直在抛出部署中的错误消息,直到我包含整个@angular 库。
另一方面,当我 运行 应用程序时,我再次看到正在下载许多单个文件,这不是我想要的。必须有一种方法可以只下载一个包含所有库的(缩小的)文件(一个包?),但我不知道该怎么做。
任何人都可以帮助我吗?
这是我的主要配置文件。
system.config.js
(function(global) {
// map tells the System loader where to look for things
var map = {
'app': 'app', // 'dist',
'@angular': 'lib/@angular',
'rxjs': 'lib/rxjs'
};
// 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' }
};
var ngPackageNames = [
'common',
'compiler',
'core',
'http',
'platform-browser',
'platform-browser-dynamic'
];
// Individual files (~300 requests):
function packIndex(pkgName) {
packages['@angular/' + pkgName] = { main: 'index.js', defaultExtension: 'js' };
}
// Add package entries for angular packages
ngPackageNames.forEach(packIndex);
var config = {
map: map,
packages: packages
};
System.config(config);
})(this);
index.html
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="./css/styles.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="lib/shim.min.js"></script>
<script src="lib/zone.js"></script>
<script src="lib/Reflect.js"></script>
<script src="lib/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
gulpfile.js
var gulp = require('gulp');
var ts = require('gulp-typescript');
const babel = require('gulp-babel');
var tsProject = ts.createProject('tsconfig.json');
gulp.task('babel-dp', ['resources', 'babel']);
gulp.task('ts-dp', ['resources', 'ts']);
gulp.task('resources', () => {
gulp.src([
'node_modules/core-js/client/shim.min.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/reflect-metadata/Reflect.js',
'node_modules/systemjs/dist/system.src.js'
]).pipe(gulp.dest('web/lib'));
gulp.src([
'node_modules/@angular/**/*',
]).pipe(gulp.dest('web/lib/@angular'));
gulp.src([
'node_modules/rxjs/**/*',
]).pipe(gulp.dest('web/lib/rxjs'));
gulp.src([
'app/**/*.js'
]).pipe(gulp.dest('web/app'));
gulp.src([
'styles.css'
]).pipe(gulp.dest('web/css'));
gulp.src([
'index.html',
'systemjs.config.js',
'favicon.ico'
]).pipe(gulp.dest('web'));
});
gulp.task('babel', () => {
return gulp.src([
'app/**/*.ts'
])
.pipe(babel({presets: ['es2015']}))
.pipe(gulp.dest('web/js'));
});
gulp.task('ts', function(done) {
var tsResult = tsProject.src([
'app/**/*.ts'
])
.pipe(ts(tsProject));
return tsResult.js.pipe(gulp.dest('web/js'));
});
如果您需要任何其他文件,请告诉我。 非常感谢!
更新
我刚刚发现我可以使用@angular 中的umd.min.js 文件而不是单个js 文件。这是一些东西,从 20 到 5MB,但当 Angular 1 的缩小版本小于 1MB 时,看起来仍然很多。
另一方面,即使我使用了这些 umd.min.js 个文件,chrome 在加载应用程序时仍然在下载单个文件。
更新 2
我设法按照评论中的建议使用 systemjs-builder 创建了一个捆绑文件。现在我有一个包含我所有应用程序代码的文件 bundle.app.js,我的 index.html 现在看起来像这样
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="css/styles.css">
<!-- 1. Load libraries -->
<script src="app/bundle.app.js"> </script>
<!-- Polyfill(s) for older browsers -->
<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>
System.import('app').catch(function(err) { console.error(err); });
</script>
</head>
<!-- 2. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
但现在 chrome 找不到在 html 中导入的 js:shim.min.js、zone.js、Reflect.js 和 system.src.js。 我在 systemjs.config.js 中添加了一行以包含 node_modules 以防万一,但我认为没有必要。无论如何,它也不起作用。这些导入不应该已经包含在捆绑包中了吗?
关于捆绑多个文件/单个文件中的库,您可以使用 gulp 任务。
这里有一些可以帮助您入门的东西。一定要明白不同线条的意思,可能会发生,你必须改变一些小部分来反映你的需要。
const gulp = require('gulp');
const path = require('path');
const runSequence = require('run-sequence');
const paths = require('../paths');
gulp.task('bundle', cb => {
runSequence(
'bundle:app',
'bundle:vendor',
cb
);
});
const app = 'app/**/*.js';
const specs = 'app/**/*.spec.js';
gulp.task('bundle:app', () => {
const appModules = `[${app}] - [${specs}]`; // except specs
return bundle(appModules, paths.dst + '/bundle.app.js', { baseUrl: paths.dst });
});
gulp.task('bundle:vendor', () => {
// build app and remove the app code - this leaves only 3rd party dependencies
const dstApp = path.join(paths.dst, app);
const dstSpecs = path.join(paths.dst, specs);
const vendorModules = `${dstApp} - [${dstApp}]`;
return bundle(vendorModules, paths.dst + '/bundle.vendor.js');
});
function bundle(src, dst, opt) {
const bundleOptions = Object.assign({
baseUrl: '.',
minify: false,
sourceMaps: false,
lowResSourceMaps: false, // mapping granularity is per-line instead of per-character
}, opt);
const Builder = require('systemjs-builder');
const builder = new Builder(bundleOptions.baseUrl, paths.src + '/systemjs.config.js');
return builder.bundle(src, dst, bundleOptions);
}
缩小是额外的步骤,但 gulp-minify 或 gulp-uglify 值得一看。
好的,我终于有了一个工作配置,所以我会把所有需要的文件复制到这里,以防有人觉得有用。
index.html
<html>
<head>
<title>Angular 2 QuickStart Deploy</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="css/styles.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="lib/shim.min.js"></script>
<script src="lib/zone.js"></script>
<script src="lib/Reflect.js"></script>
<script src="lib/system.src.js"></script>
</head>
<!-- 2. Display the application -->
<body>
<my-app>Loading...</my-app>
<!-- application bundle -->
<script src="app/bundle.app.js"></script>
</body>
</html>
gulpfile.js
const gulp = require('gulp');
const ts = require('gulp-typescript');
const babel = require('gulp-babel');
const Builder = require('systemjs-builder');
// systemjs-builder
const builder = new Builder('.', 'systemjs.config.js');
// typescript transpiler
var tsProject = ts.createProject('tsconfig.json');
gulp.task('babel-dp', ['resources', 'babel']);
gulp.task('ts-dp', ['resources', 'ts']);
gulp.task('bundle:app', () => {
builder.buildStatic('app/*.js', 'web/app/bundle.app.js')
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.log('error ' + err);
})
})
gulp.task('resources', () => {
gulp.src([
'node_modules/core-js/client/shim.min.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/reflect-metadata/Reflect.js',
'node_modules/systemjs/dist/system.src.js'
]).pipe(gulp.dest('web/lib'));
gulp.src([
'styles.css'
]).pipe(gulp.dest('web/css'));
gulp.src([
'index.html',
'favicon.ico'
]).pipe(gulp.dest('web'));
});
gulp.task('babel', () => {
return gulp.src([
'app/**/*.ts'
])
.pipe(babel({presets: ['es2015']}))
.pipe(gulp.dest('web/js'));
});
gulp.task('ts', function(done) {
var tsResult = tsProject.src([
'app/**/*.ts'
])
.pipe(ts(tsProject));
//return tsResult.js.pipe(gulp.dest('web/js'));
return tsResult.js.pipe(gulp.dest('app/js'));
});
其余文件没有改变。 这里对我来说要点是使用 systemjs-builder 创建包(感谢@Thorsten 的提示)和在 index.html.
中使用包