Programming

프로덕션 용 Angular 앱 번들 방법

procodes 2020. 3. 5. 08:00
반응형

프로덕션 용 Angular 앱 번들 방법


라이브 웹 서버에서 프로덕션을 위해 Angular (버전 2, 4, 6, ...)를 번들로 묶는 가장 좋은 방법은 무엇입니까?

이후 버전으로 이동할 때 더 잘 추적 할 수 있도록 Angular 버전을 답변 내에 포함 시키십시오.


2.x, 4.x, 5.x, 6.x, 7.x, 8.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)에 생성됩니다.

산출

8.2.5CLI가 있는 Angular 8.3.3및 각도 라우팅이없는 옵션 CSS의 크기

  • dist/main-[es-version].[hash].js응용 프로그램 번들 [ES5 크기 : 새 Angular CLI 응용 프로그램의 경우 183KB, 압축 된 44 KB ].
  • dist/polyfill-[es-version].[hash].bundle.jspolyfill 종속성 (@angular, RxJS ...) 번들 [ES5 크기 : 신규 각도 CLI 애플리케이션 1백22킬로바이트 비우 36킬로바이트 압축].
  • 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 (가능한 한 작게)]
    • 전체 프레임 워크가 아닌 rxjs 및 각도 의존성 포함
  • bundles/app.bundle.js[ 크기 : 귀하의 프로젝트에 따라 다릅니다 , 내 ~ 0.5 MB ]
    • 프로젝트를 포함

파일 구조

  • projectFolder / app / (모든 구성 요소, 지시문, 템플릿 등)
  • projectFolder / gulpfile.js

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);
    });
});
  • projectFolder / package.json ( 빠른 시작 안내서 와 동일 , 번들에 필요한 devDependencies 및 npm 스크립트가 표시됨)

{
  "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"
  }
}
  • projectFolder / systemjs.config.js ( 빠른 시작 안내서 와 동일 하지만 더 이상 사용할 수 없음)

(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);
  • projetcFolder / dist-systemjs.config.js (systemjs.config.json과의 차이점 만 표시)

var map = {
    'app':                        'dist/app',
  };
  • projectFolder / index.html (제작)- 스크립트 태그의 순서가 중요합니다. 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>
  • projectFolder / app / boot.ts 는 부트 스트랩이있는 곳입니다.

내가 아직 할 수있는 최선 :)


Webpack이있는 Angular 2 (CLI 설정 없음)

1- Angular2 팀의 튜토리얼

Angular2 팀은 Webpack 사용을 위한 튜토리얼발표했습니다

튜토리얼에서 파일을 만들어 작은 GitHub 시드 프로젝트에 배치했습니다 . 따라서 워크 플로우를 빠르게 시도 할 수 있습니다.

지침 :

  • npm 설치

  • npm start . 개발을 위해. 로컬 호스트 주소에 라이브로로드 될 가상 "dist"폴더가 생성됩니다.

  • npm run build . 생산 용. "이것은 웹 서버로 전송 될 수있는 것보다 실제"dist "폴더 버전을 생성합니다. dist 폴더는 7.8MB이지만 실제로 웹 브라우저에 페이지를로드하려면 234KB 만 필요합니다.

2-웹킷 스타터 키트

Webpack Starter Kit 는 위의 튜토리얼보다 더 많은 테스트 기능을 제공하며 상당히 인기가 있습니다.


SystemJs 빌더 및 Gulp를 사용한 Angular 2 프로덕션 워크 플로우

Angular.io에는 빠른 시작 자습서가 있습니다. 이 튜토리얼을 복사하고 서버에 복사 할 수있는 dist 폴더에 모든 것을 묶는 간단한 gulp 작업으로 확장했습니다. Jenkis CI에서 잘 작동하도록 모든 것을 최적화하려고 시도했기 때문에 node_modules를 캐시 할 수 있으며 복사 할 필요가 없습니다.

Github의 샘플 앱이있는 소스 코드 : https://github.com/Anjmao/angular2-production-workflow

생산 단계
  1. 깨끗한 typescripts 컴파일 된 js 파일 및 dist 폴더
  2. 앱 폴더 내에서 타이프 스크립트 파일 컴파일
  3. SystemJs 번 들러를 사용하여 브라우저 캐시 새로 고침을 위해 생성 된 해시와 함께 모든 파일을 dist 폴더에 묶습니다.
  4. gulp-html-replace를 사용하여 index.html 스크립트를 번들 버전으로 바꾸고 dist 폴더로 복사하십시오.
  5. 자산 폴더 내부의 모든 것을 dist 폴더로 복사

Node : 항상 자체 빌드 프로세스를 만들 수는 있지만 필요한 모든 워크 플로우가 있으며 완벽하게 작동하므로 angular-cli를 사용하는 것이 좋습니다. 우리는 이미 프로덕션 환경에서 사용하고 있으며 앵귤러 클리에는 전혀 문제가 없습니다.


Angular CLI 1.xx (Angular 4.xx, 5.xx와 호환)

이것은 다음을 지원합니다.

  • 각도 2.x 및 4.x
  • 최신 웹팩 2.x
  • 각도 AoT 컴파일러
  • 라우팅 (정상 및 게으른)
  • SCSS
  • 커스텀 파일 번들링 (자산)
  • 추가 개발 도구 (리터, 유닛 및 엔드 투 엔드 테스트 설정)

초기 설정

새로운 프로젝트 이름-라우팅

--style=scssSASS .scss 지원을 위해 추가 할 수 있습니다 .

--ng4Angular 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
    생성 / 가져온 모든 .js 스크립트를 포함하는 기본 .js 파일
  • ./dist/styles.<content-hash>.bundle.js
    CLI 방식 인 CSS에 Webpack 로더를 사용하면 여기에서 JS를 통해로드됩니다.

이전 버전에서는 크기 및 .map소스 맵 파일 을 확인하기 위해 gzipped 버전을 만들었지 만 사람들이 계속 제거하도록 요청함에 따라 더 이상 발생하지 않습니다.

다른 파일들

다른 경우에는 원치 않는 다른 파일 / 폴더가있을 수 있습니다.

  • ./out-tsc/
    ./src/tsconfig.jsonoutDir
  • ./out-tsc-e2e/
    ./e2e/tsconfig.jsonoutDir
  • ./dist/ngfactory/
    AoT 컴파일러에서 (베타 16부터 CLI를 포크하지 않고는 구성 할 수 없음)

현재까지도 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 앱의 다운로드 크기, 파일 수 등을 보여주는 간단한 비디오를 만들었습니다. 여기에서 볼 수 있습니다.

https://youtu.be/ZoZDCgQwnmQ

비디오에서 사용 된 소스 코드는 다음과 같습니다.

https://github.com/fintechneo/angular2-templates


        **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="/">
    </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-ghpagesgithub사용 하여 앵귤러 응용 프로그램을 배포 할 수 있습니다

이 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 doc을 따르십시오.

https://github.com/roshan3133/angular2-webpack-starter


현재 프로젝트 디렉토리에서 아래 CLI 명령을 시도하십시오. dist 폴더 번들을 작성합니다. 배포를 위해 dist 폴더 내의 모든 파일을 업로드 할 수 있습니다.

ng build --prod --aot --base-href.

참고 URL : https://stackoverflow.com/questions/37631098/how-to-bundle-an-angular-app-for-production



반응형