라이브 웹 서버에서 프로덕션을 위해 Angular (버전 2, 4, 6, ...)를 번들로 묶는 가장 좋은 방법은 무엇입니까?
이후 버전으로 이동할 때 더 잘 추적 할 수 있도록 답변에 Angular 버전을 포함하십시오.
라이브 웹 서버에서 프로덕션을 위해 Angular (버전 2, 4, 6, ...)를 번들로 묶는 가장 좋은 방법은 무엇입니까?
이후 버전으로 이동할 때 더 잘 추적 할 수 있도록 답변에 Angular 버전을 포함하십시오.
답변:
2.x, 4.x, 5.x, 6.x, 7.x, 8.x, 9.x
Angular CLI가있는 (TypeScript)npm install -g @angular/cli
ng new projectFolder
새로운 응용 프로그램을 만듭니다ng build --prod
(디렉토리가 인 경우 명령 행에서 실행 projectFolder
)
prod
생산을위한 플래그 번들 ( 생산 플래그에 포함 된 옵션 목록은 Angular 설명서 를 참조하십시오 ).
Brotli를 사용하여 압축 다음 명령을 사용하여 리소스를 압축
for i in dist/*; do brotli $i; done
번들은 기본적으로 projectFolder / dist (/ $ projectFolder for 6)에 생성됩니다.
9.0.0
CLI가 있는 Angular 9.0.1
및 각도 라우팅이없는 옵션 CSS의 크기
dist/main-[es-version].[hash].js
애플리케이션 번들 [ES5 크기 : 새 Angular CLI 애플리케이션의 경우 158KB, 40KB 압축].dist/polyfill-[es-version].[hash].bundle.js
polyfill 종속성 (@angular, RxJS ...) 번들 [ES5 크기 : 비어있는 새 Angular CLI 응용 프로그램의 경우 127KB, 압축 된 37KB ].dist/index.html
응용 프로그램의 시작점.dist/runtime-[es-version].[hash].bundle.js
웹팩 로더dist/style.[hash].bundle.css
스타일 정의dist/assets
Angular CLI 자산 구성에서 복사 된 자원http : // localhost : 4200을ng serve --prod
사용하여 프로덕션 파일이있는 애플리케이션에 액세스 할 수 있도록 로컬 HTTP 서버를 시작하는 명령을 사용하여 애플리케이션의 미리보기를 얻을 수 있습니다 .
프로덕션 용도의 경우 dist
선택한 HTTP 서버의 폴더에서 모든 파일을 배포 해야합니다.
2.0.1 Final
Gulp 사용 (TypeScript-대상 : ES5)npm install
(direcory가 projectFolder 인 경우 cmd에서 실행)npm run bundle
(direcory가 projectFolder 인 경우 cmd에서 실행)
번들은 projectFolder / bundles /
bundles/dependencies.bundle.js
[ 크기 : ~ 1MB (가능한 한 작게)]
bundles/app.bundle.js
[ 크기 : 귀하의 프로젝트에 따라 다릅니다 , 내 ~ 0.5 MB ]
var gulp = require('gulp'),
tsc = require('gulp-typescript'),
Builder = require('systemjs-builder'),
inlineNg2Template = require('gulp-inline-ng2-template');
gulp.task('bundle', ['bundle-app', 'bundle-dependencies'], function(){});
gulp.task('inline-templates', function () {
return gulp.src('app/**/*.ts')
.pipe(inlineNg2Template({ useRelativePaths: true, indent: 0, removeLineBreaks: true}))
.pipe(tsc({
"target": "ES5",
"module": "system",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": true,
"noImplicitAny": false
}))
.pipe(gulp.dest('dist/app'));
});
gulp.task('bundle-app', ['inline-templates'], function() {
// optional constructor options
// sets the baseURL and loads the configuration file
var builder = new Builder('', 'dist-systemjs.config.js');
return builder
.bundle('dist/app/**/* - [@angular/**/*.js] - [rxjs/**/*.js]', 'bundles/app.bundle.js', { minify: true})
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.log('Build error');
console.log(err);
});
});
gulp.task('bundle-dependencies', ['inline-templates'], function() {
// optional constructor options
// sets the baseURL and loads the configuration file
var builder = new Builder('', 'dist-systemjs.config.js');
return builder
.bundle('dist/app/**/*.js - [dist/app/**/*.js]', 'bundles/dependencies.bundle.js', { minify: true})
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.log('Build error');
console.log(err);
});
});
{
"name": "angular2-quickstart",
"version": "1.0.0",
"scripts": {
***
"gulp": "gulp",
"rimraf": "rimraf",
"bundle": "gulp bundle",
"postbundle": "rimraf dist"
},
"license": "ISC",
"dependencies": {
***
},
"devDependencies": {
"rimraf": "^2.5.2",
"gulp": "^3.9.1",
"gulp-typescript": "2.13.6",
"gulp-inline-ng2-template": "2.0.1",
"systemjs-builder": "^0.15.16"
}
}
(function(global) {
// map tells the System loader where to look for things
var map = {
'app': 'app',
'rxjs': 'node_modules/rxjs',
'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
'@angular': 'node_modules/@angular'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'app/boot.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { defaultExtension: 'js' }
};
var packageNames = [
'@angular/common',
'@angular/compiler',
'@angular/core',
'@angular/forms',
'@angular/http',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'@angular/router-deprecated',
'@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' };
});
var config = {
map: map,
packages: packages
};
// filterSystemConfig - index.asp's chance to modify config before we register it.
if (global.filterSystemConfig) { global.filterSystemConfig(config); }
System.config(config);
})(this);
var map = {
'app': 'dist/app',
};
dist-systemjs.config.js
번들 태그 뒤에 태그를 배치하면 프로그램을 계속 실행할 수 있지만 종속성 번들은 무시되고 node_modules
폴더 에서 종속성이로드됩니다 .<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<base href="/"/>
<title>Angular</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<my-app>
loading...
</my-app>
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.min.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.js"></script>
<script src="dist-systemjs.config.js"></script>
<!-- Project Bundles. Note that these have to be loaded AFTER the systemjs.config script -->
<script src="bundles/dependencies.bundle.js"></script>
<script src="bundles/app.bundle.js"></script>
<script>
System.import('app/boot').catch(function (err) {
console.error(err);
});
</script>
</body>
</html>
내가 아직 할 수있는 최선 :)
inline-templates
실행 되면 템플릿을 인라인 한 다음에 모든 앱 폴더 및 파일의 복사본을 만듭니다 dist/app
. 그런 다음에 dist-systemjs.config.js
당신이지도 app
에 dist/app
있는 당신이 사용하는 경우 존재하지 않습니다 폴더입니다 dist
루트로 폴더를. dist
폴더 에서 앱을 실행하지 않겠습니까 ? 이 경우 dist
루트 dist
폴더 에 폴더가 중첩되어 있지 않습니다 . 나는 여기에 다른 것을 놓치고 있어야합니다. dist/app
폴더 에있는 일반적인 파일이 아니라 번들 파일을 사용하도록 systemjs에 지시 할 필요가 없습니까?
Angular2 팀은 Webpack 사용을 위한 튜토리얼 을 발표했습니다
튜토리얼에서 파일을 만들어 작은 GitHub 시드 프로젝트에 배치했습니다 . 따라서 워크 플로우를 신속하게 시도 할 수 있습니다.
지침 :
npm 설치
npm start . 개발을 위해. 로컬 호스트 주소에 라이브로로드 될 가상 "dist"폴더가 생성됩니다.
npm run build . 생산 용. "이것은 웹 서버로 전송 될 수있는 것보다 실제"dist "폴더 버전을 생성합니다. dist 폴더는 7.8MB이지만 웹 브라우저에 페이지를로드하는 데 실제로 234KB 만 필요합니다.
이 Webpack 스타터 키트 는 위의 튜토리얼보다 더 많은 테스트 기능을 제공하며 상당히 인기가 있습니다.
Angular.io에는 빠른 시작 자습서가 있습니다. 이 튜토리얼을 복사하고 서버에 복사 할 수있는 dist 폴더에 모든 것을 묶는 간단한 gulp 작업으로 확장했습니다. Jenkis CI에서 잘 작동하도록 모든 것을 최적화하려고 시도했기 때문에 node_modules를 캐시 할 수 있으며 복사 할 필요가 없습니다.
Github의 샘플 앱이있는 소스 코드 : https://github.com/Anjmao/angular2-production-workflow
생산 단계Node : 항상 자체 빌드 프로세스를 만들 수는 있지만 필요한 모든 워크 플로우가 있으며 완벽하게 작동하므로 angular-cli를 사용하는 것이 좋습니다. 우리는 이미 프로덕션 환경에서 사용하고 있으며 앵귤러 클리에는 전혀 문제가 없습니다.
이것은 다음을 지원합니다.
새로운 프로젝트 이름-라우팅
--style=scss
SASS .scss 지원을 위해 추가 할 수 있습니다 .
--ng4
Angular 2 대신 Angular 4를 사용하여 추가 할 수 있습니다 .
프로젝트를 생성하면 CLI가 자동으로 실행 npm install
됩니다. Yarn을 대신 사용하거나 설치하지 않고 프로젝트 스켈레톤을 보려면 여기에서 수행 방법을 확인하십시오 .
프로젝트 폴더 내부 :
ng 빌드 -prod
현재 버전 --aot
에서는 개발 모드에서 사용할 수 있기 때문에 수동으로 지정 해야합니다 (느려져서 실용적이지는 않지만).
또한 더 작은 번들 (Angular 컴파일러가 아니라 생성 된 컴파일러 출력)에 대해 AoT 컴파일을 수행합니다. 생성 된 코드가 작을 때 Angular 4를 사용하면 번들은 AoT에서 훨씬 작습니다.
개발 모드 (소스 맵, 축소 없음) 및 AoT를 실행하여 AoT로 앱을 테스트 할 수 있습니다.ng build --aot
.
기본 출력 디렉토리는 ./dist
에서 변경할 수 있지만 ./angular-cli.json
.
빌드 단계의 결과는 다음과 같습니다.
(참고 : <content-hash>
캐시 무효화 방식으로 의도 된 파일 내용의 해시 / 지문을 나타냅니다. 이는 Webpack script
이 자체적으로 태그를 작성하기 때문에 가능 합니다)
./dist/assets
./src/assets/**
./dist/index.html
./src/index.html
웹팩 스크립트를 추가 한 후 ./angular-cli.json
./dist/inline.js
./dist/main.<content-hash>.bundle.js
./dist/styles.<content-hash>.bundle.js
이전 버전에서는 크기 및 .map
소스 맵 파일 을 확인하기 위해 gzipped 버전을 만들었지 만 사람들이 계속 제거하도록 요청함에 따라 더 이상 발생하지 않습니다.
다른 경우에는 원치 않는 다른 파일 / 폴더가있을 수 있습니다.
./out-tsc/
./src/tsconfig.json
의outDir
./out-tsc-e2e/
./e2e/tsconfig.json
의outDir
./dist/ngfactory/
<content-hash>
prod의 번들에서 제거하면 어떻게됩니까? 최신 번들을 얻는 데 문제가 발생할 수 있습니까?
현재까지도 Ahead-of-Time Compilation 요리 책을 프로덕션 번들링을위한 최고의 레시피로 여깁니다. 여기에서 찾을 수 있습니다. https://angular.io/docs/ts/latest/cookbook/aot-compiler.html
지금까지 Angular 2에 대한 나의 경험은 AoT가 로딩 시간이 거의없이 가장 작은 빌드를 생성한다는 것입니다. 여기서 가장 중요한 질문은 프로덕션에 몇 개의 파일 만 보내면됩니다.
템플릿이 "Ahead of Time"으로 컴파일되므로 Angular 컴파일러는 프로덕션 빌드와 함께 제공되지 않기 때문입니다. HTML 템플릿 마크 업이 자바 스크립트 명령어로 변환되어 원래의 HTML로 리버스 엔지니어링하기가 매우 어려울 수도 있습니다.
dev와 AoT 빌드의 Angular 2 앱의 다운로드 크기, 파일 수 등을 보여주는 간단한 비디오를 만들었습니다. 여기에서 볼 수 있습니다.
비디오에서 사용 된 소스 코드는 다음과 같습니다.
**Production build with
- Angular Rc5
- Gulp
- typescripts
- systemjs**
1)con-cat all js files and css files include on index.html using "gulp-concat".
- styles.css (all css concat in this files)
- shims.js(all js concat in this files)
2)copy all images and fonts as well as html files with gulp task to "/dist".
3)Bundling -minify angular libraries and app components mentioned in systemjs.config.js file.
Using gulp 'systemjs-builder'
SystemBuilder = require('systemjs-builder'),
gulp.task('system-build', ['tsc'], function () {
var builder = new SystemBuilder();
return builder.loadConfig('systemjs.config.js')
.then(function () {
builder.buildStatic('assets', 'dist/app/app_libs_bundle.js')
})
.then(function () {
del('temp')
})
});
4)Minify bundles using 'gulp-uglify'
jsMinify = require('gulp-uglify'),
gulp.task('minify', function () {
var options = {
mangle: false
};
var js = gulp.src('dist/app/shims.js')
.pipe(jsMinify())
.pipe(gulp.dest('dist/app/'));
var js1 = gulp.src('dist/app/app_libs_bundle.js')
.pipe(jsMinify(options))
.pipe(gulp.dest('dist/app/'));
var css = gulp.src('dist/css/styles.min.css');
return merge(js,js1, css);
});
5) In index.html for production
<html>
<head>
<title>Hello</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8" />
<link rel="stylesheet" href="app/css/styles.min.css" />
<script type="text/javascript" src="app/shims.js"></script>
<base href="https://stackoverflow.com/">
</head>
<body>
<my-app>Loading...</my-app>
<script type="text/javascript" src="app/app_libs_bundle.js"></script>
</body>
</html>
6) Now just copy your dist folder to '/www' in wamp server node need to copy node_modules in www.
angular-cli-ghpages 를 github
사용
하여 앵귤러 응용 프로그램을 배포 할 수 있습니다
이 cli를 사용하여 배포하는 방법을 찾으려면 링크를 확인하십시오.
배포 된 웹 사이트는 github
일반적으로 일부 지점에 저장됩니다.
gh-pages
git 브랜치를 복제하여 서버의 정적 웹 사이트처럼 사용할 수 있습니다.
"최상"은 시나리오에 따라 다릅니다. 가장 작은 단일 번들 만 신경 쓰는 경우가 있지만 큰 앱에서는 지연로드를 고려해야 할 수도 있습니다. 어느 시점에서 전체 앱을 단일 번들로 제공하는 것은 실용적이지 않습니다.
후자의 경우 Webpack은 일반적으로 코드 분할을 지원하므로 가장 좋은 방법입니다.
단일 번들의 경우 롤업 또는 용감하다고 생각되는 경우 폐쇄 컴파일러를 고려하십시오.
여기에서 사용한 모든 Angular 번 들러의 샘플을 만들었습니다. http://www.syntaxsuccess.com/viewarticle/angular-production-builds
코드는 여기에서 찾을 수 있습니다. https://github.com/thelgevold/angular-2-samples
각도 버전 : 4.1.x
1 분 안에 webpack 3으로 앵귤러 4를 설정하기 만하면 개발 및 프로덕션 ENV 번들이 문제없이 준비 될 것입니다. 아래 github 문서를 따르십시오.
현재 프로젝트 디렉토리에서 아래 CLI 명령을 시도하십시오. dist 폴더 번들을 작성합니다. 배포를 위해 dist 폴더 내의 모든 파일을 업로드 할 수 있습니다.
ng build --prod --aot --base-href.
ng serve는 개발 목적으로 응용 프로그램을 제공하기 위해 작동합니다. 생산은 어떻습니까? package.json 파일을 살펴보면 사용할 수있는 스크립트가 있음을 알 수 있습니다.
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
빌드 스크립트는 --prod 플래그와 함께 Angular CLI의 ng 빌드를 사용합니다. 지금 해보자. 두 가지 방법 중 하나를 수행 할 수 있습니다.
# npm 스크립트 사용
npm run build
# cli를 직접 사용
ng build --prod
이번에는 5 개 대신 4 개의 파일이 제공됩니다. --prod 플래그는 Angular에게 응용 프로그램의 크기를 훨씬 작게 만들도록 지시합니다.